From: Apple Date: Fri, 28 Jan 2005 07:16:32 +0000 (+0000) Subject: mDNSResponder-58.8.1.tar.gz X-Git-Tag: mac-os-x-1039^0 X-Git-Url: https://git.saurik.com/apple/mdnsresponder.git/commitdiff_plain/b7388343e7dbd0ce526282fbd93d546e3b0610db mDNSResponder-58.8.1.tar.gz --- diff --git a/Clients/DNSServiceBrowser.m b/Clients/DNSServiceBrowser.m new file mode 100755 index 0000000..c11cb68 --- /dev/null +++ b/Clients/DNSServiceBrowser.m @@ -0,0 +1,541 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: DNSServiceBrowser.m,v $ +Revision 1.18 2003/08/12 19:55:07 cheshire +Update to APSL 2.0 + + */ + +#import "BrowserController.h" + +#include "arpa/inet.h" + +void +MyHandleMachMessage ( CFMachPortRef port, void * msg, CFIndex size, void * info ) +{ + DNSServiceDiscovery_handleReply(msg); +} + +void browse_reply ( + DNSServiceBrowserReplyResultType resultType, // One of DNSServiceBrowserReplyResultType + const char *replyName, + const char *replyType, + const char *replyDomain, + DNSServiceDiscoveryReplyFlags flags, // DNS Service Discovery reply flags information + void *context + ) +{ + [[NSApp delegate] updateBrowseWithResult:resultType name:[NSString stringWithUTF8String:replyName] type:[NSString stringWithUTF8String:replyType] domain:[NSString stringWithUTF8String:replyDomain] flags:flags]; + return; +} + +void enum_reply ( + DNSServiceDomainEnumerationReplyResultType resultType, + const char *replyDomain, + DNSServiceDiscoveryReplyFlags flags, + void *context + ) +{ + [[NSApp delegate] updateEnumWithResult:resultType domain:[NSString stringWithUTF8String:replyDomain] flags:flags]; + + return; +} + +void resolve_reply ( + struct sockaddr *interface, + struct sockaddr *address, + const char *txtRecord, + DNSServiceDiscoveryReplyFlags flags, + void *context + ) +{ + [[NSApp delegate] resolveClientWithInterface:interface address:address txtRecord:[NSString stringWithUTF8String:txtRecord]]; + + return; +} + +@implementation BrowserController //Begin implementation of BrowserController methods + +- (void)registerDefaults +{ + NSMutableDictionary *regDict = [NSMutableDictionary dictionary]; + + NSArray *typeArray = [NSArray arrayWithObjects:@"_ftp._tcp.", @"_tftp._tcp.", + @"_ssh._tcp.", @"_telnet._tcp.", + @"_http._tcp.", + @"_printer._tcp.", @"_ipp._tcp.", + @"_ichat._tcp.", @"_eppc._tcp.", + @"_afpovertcp._tcp.", @"_afpovertcp._tcp.", @"_MacOSXDupSuppress._tcp.", nil]; + NSArray *nameArray = [NSArray arrayWithObjects:@"File Transfer (ftp)", @"Trivial File Transfer (tftp)", + @"Secure Shell (ssh)", @"Telnet", + @"Web Server (http)", + @"LPR Printer", @"IPP Printer", + @"iChat", @"Remote AppleEvents", + @"AppleShare Server", @"SMB File Server", @"Mystery Service", nil]; + + [regDict setObject:typeArray forKey:@"SrvTypeKeys"]; + [regDict setObject:nameArray forKey:@"SrvNameKeys"]; + + [[NSUserDefaults standardUserDefaults] registerDefaults:regDict]; +} + + +- (id)init +{ + [self registerDefaults]; + + browse_client = nil; + + return [super init]; +} + +- (void)awakeFromNib //BrowserController startup procedure +{ + SrvType=NULL; + Domain=NULL; + srvtypeKeys = [NSMutableArray array]; //Define arrays for Type, Domain, and Name + srvnameKeys = [NSMutableArray array]; + + domainKeys = [NSMutableArray array]; + [domainKeys retain]; + + nameKeys = [NSMutableArray array]; + [nameKeys retain]; + + [srvtypeKeys retain]; //Keep arrays in memory until BrowserController closes + [srvnameKeys retain]; //Keep arrays in memory until BrowserController closes + [typeField setDataSource:self]; //Set application fields' data source to BrowserController + [typeField sizeLastColumnToFit]; //and set column sizes to use their whole table's width. + [nameField setDataSource:self]; + [nameField sizeLastColumnToFit]; + [domainField setDataSource:self]; + [domainField sizeLastColumnToFit]; + + [nameField setDoubleAction:@selector(connect:)]; + + //[srvtypeKeys addObject:@"_ftp._tcp."]; //Add supported protocols and domains to their + //[srvnameKeys addObject:@"File Transfer (ftp)"]; + //[srvtypeKeys addObject:@"_printer._tcp."]; //respective arrays + //[srvnameKeys addObject:@"Printer (lpr)"]; + //[srvtypeKeys addObject:@"_http._tcp."]; //respective arrays + //[srvnameKeys addObject:@"Web Server (http)"]; + //[srvtypeKeys addObject:@"_afp._tcp."]; //respective arrays + //[srvnameKeys addObject:@"AppleShare Server (afp)"]; + + [ipAddressField setStringValue:@""]; + [portField setStringValue:@""]; + [textField setStringValue:@""]; + + [srvtypeKeys addObjectsFromArray:[[NSUserDefaults standardUserDefaults] arrayForKey:@"SrvTypeKeys"]]; + [srvnameKeys addObjectsFromArray:[[NSUserDefaults standardUserDefaults] arrayForKey:@"SrvNameKeys"]]; + + + [typeField reloadData]; //Reload (redraw) data in fields + [domainField reloadData]; + + [self loadDomains:self]; + +} + +- (void)dealloc //Deallocation method +{ + [srvtypeKeys release]; + [srvnameKeys release]; + [nameKeys release]; + [domainKeys release]; +} + +-(void)tableView:(NSTableView *)theTableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(int)row +{ + if (row<0) return; +} + +- (int)numberOfRowsInTableView:(NSTableView *)theTableView //Begin mandatory TableView methods +{ + if (theTableView == typeField) + { + return [srvnameKeys count]; + } + if (theTableView == domainField) + { + return [domainKeys count]; + } + if (theTableView == nameField) + { + return [nameKeys count]; + } + if (theTableView == serviceDisplayTable) + { + return [srvnameKeys count]; + } + return 0; +} + +- (id)tableView:(NSTableView *)theTableView objectValueForTableColumn:(NSTableColumn *)theColumn row:(int)rowIndex +{ + if (theTableView == typeField) + { + return [srvnameKeys objectAtIndex:rowIndex]; + } + if (theTableView == domainField) + { + return [domainKeys objectAtIndex:rowIndex]; + } + if (theTableView == nameField) + { + return [[nameKeys sortedArrayUsingSelector:@selector(compare:)] objectAtIndex:rowIndex]; + } + if (theTableView == serviceDisplayTable) + { + if (theColumn == typeColumn) { + return [srvtypeKeys objectAtIndex:rowIndex]; + } + if (theColumn == nameColumn) { + return [srvnameKeys objectAtIndex:rowIndex]; + } + return 0; + } + else + return(0); +} //End of mandatory TableView methods + +- (IBAction)handleTypeClick:(id)sender //Handle clicks for Type +{ + int index=[sender selectedRow]; //Find index of selected row + if (index==-1) return; //Error checking + SrvType = [srvtypeKeys objectAtIndex:index]; //Save desired Type + SrvName = [srvnameKeys objectAtIndex:index]; //Save desired Type + + [ipAddressField setStringValue:@""]; + [portField setStringValue:@""]; + [textField setStringValue:@""]; + + [self update:SrvType Domain:Domain]; //If Type and Domain are set, update records +} + +- (IBAction)handleDomainClick:(id)sender //Handle clicks for Domain +{ + int index=[sender selectedRow]; //Find index of selected row + if (index==-1) return; //Error checking + Domain = [domainKeys objectAtIndex:index]; //Save desired Domain + + [ipAddressField setStringValue:@""]; + [portField setStringValue:@""]; + [textField setStringValue:@""]; + + if (SrvType!=NULL) [self update:SrvType Domain:Domain]; //If Type and Domain are set, update records +} + +- (IBAction)handleNameClick:(id)sender //Handle clicks for Name +{ + int index=[sender selectedRow]; //Find index of selected row + if (index==-1) return; //Error checking + Name=[[nameKeys sortedArrayUsingSelector:@selector(compare:)] objectAtIndex:index]; //Save desired name + + { + CFMachPortRef cfMachPort; + CFMachPortContext context; + Boolean shouldFreeInfo; + dns_service_discovery_ref dns_client; + mach_port_t port; + CFRunLoopSourceRef rls; + + context.version = 1; + context.info = 0; + context.retain = NULL; + context.release = NULL; + context.copyDescription = NULL; + + [ipAddressField setStringValue:@"?"]; + [portField setStringValue:@"?"]; + [textField setStringValue:@"?"]; + // start an enumerator on the local server + dns_client = DNSServiceResolverResolve + ( + (char *)[Name UTF8String], + (char *)[SrvType UTF8String], + (char *)(Domain?[Domain UTF8String]:""), + resolve_reply, + nil + ); + + port = DNSServiceDiscoveryMachPort(dns_client); + + if (port) { + cfMachPort = CFMachPortCreateWithPort ( kCFAllocatorDefault, port, ( CFMachPortCallBack ) MyHandleMachMessage,&context,&shouldFreeInfo ); + + /* Create and add a run loop source for the port */ + rls = CFMachPortCreateRunLoopSource(NULL, cfMachPort, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); + CFRelease(rls); + } else { + printf("Could not obtain client port\n"); + return; + } + } +} + +- (IBAction)loadDomains:(id)sender +{ + CFMachPortRef cfMachPort; + CFMachPortContext context; + Boolean shouldFreeInfo; + dns_service_discovery_ref dns_client; + mach_port_t port; + CFRunLoopSourceRef rls; + + context.version = 1; + context.info = 0; + context.retain = NULL; + context.release = NULL; + context.copyDescription = NULL; + + // start an enumerator on the local server + dns_client = DNSServiceDomainEnumerationCreate + ( + 0, + enum_reply, + nil + ); + + port = DNSServiceDiscoveryMachPort(dns_client); + + if (port) { + cfMachPort = CFMachPortCreateWithPort ( kCFAllocatorDefault, port, ( CFMachPortCallBack ) MyHandleMachMessage,&context,&shouldFreeInfo ); + + /* Create and add a run loop source for the port */ + rls = CFMachPortCreateRunLoopSource(NULL, cfMachPort, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); + CFRelease(rls); + } else { + printf("Could not obtain client port\n"); + return; + } +} + +- (IBAction)update:theType Domain:theDomain; //The Big Kahuna: Fetch PTR records and update application +{ + const char * DomainC; + const char * TypeC=[theType UTF8String]; //Type in C string format + + if (theDomain) { + DomainC = [theDomain UTF8String]; //Domain in C string format + } else { + DomainC = ""; + } + + [nameKeys removeAllObjects]; //Get rid of displayed records if we're going to go get new ones + [nameField reloadData]; //Reload (redraw) names to show the old data is gone + + // get rid of the previous browser if one exists + if (browse_client) { + DNSServiceDiscoveryDeallocate(browse_client); + browse_client = nil; + } + + // now create a browser to return the values for the nameField ... + { + CFMachPortRef cfMachPort; + CFMachPortContext context; + Boolean shouldFreeInfo; + mach_port_t port; + CFRunLoopSourceRef rls; + + context.version = 1; + context.info = 0; + context.retain = NULL; + context.release = NULL; + context.copyDescription = NULL; + + // start an enumerator on the local server + browse_client = DNSServiceBrowserCreate + ( + (char *)TypeC, + (char *)DomainC, + browse_reply, + nil + ); + + port = DNSServiceDiscoveryMachPort(browse_client); + + if (port) { + cfMachPort = CFMachPortCreateWithPort ( kCFAllocatorDefault, port, ( CFMachPortCallBack ) MyHandleMachMessage,&context,&shouldFreeInfo ); + + /* Create and add a run loop source for the port */ + rls = CFMachPortCreateRunLoopSource(NULL, cfMachPort, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); + CFRelease(rls); + } else { + printf("Could not obtain client port\n"); + return; + } + } + +} + + +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication //Quit when main window is closed +{ + return YES; +} + +- (BOOL)windowShouldClose:(NSWindow *)sender //Save domains to our domain file when quitting +{ + [domainField reloadData]; + return YES; +} + +- (void)updateEnumWithResult:(int)resultType domain:(NSString *)domain flags:(int)flags +{ + // new domain received + if (DNSServiceDomainEnumerationReplyAddDomain == resultType || DNSServiceDomainEnumerationReplyAddDomainDefault == resultType) { + // add the domain to the list + [domainKeys addObject:domain]; + } else { + // remove the domain from the list + NSEnumerator *dmnEnum = [domainKeys objectEnumerator]; + NSString *aDomain = nil; + + while (aDomain = [dmnEnum nextObject]) { + if ([aDomain isEqualToString:domain]) { + [domainKeys removeObject:domain]; + break; + } + } + } + // update the domain table + [domainField reloadData]; + return; +} + + + +- (void)updateBrowseWithResult:(int)type name:(NSString *)name type:(NSString *)resulttype domain:(NSString *)domain flags:(int)flags +{ + + //NSLog(@"Received result %@ %@ %@ %d", name, resulttype, domain, type); + + if (([domain isEqualToString:Domain] || [domain isEqualToString:@"local."]) && [resulttype isEqualToString:SrvType]) { + + if (type == DNSServiceBrowserReplyRemoveInstance) { + if ([nameKeys containsObject:name]) { + [nameKeys removeObject:name]; + } + } + if (type == DNSServiceBrowserReplyAddInstance) { + if (![nameKeys containsObject:name]) { + [nameKeys addObject:name]; + } + } + + // If not expecting any more data, then reload (redraw) Name TableView with newly found data + if ((flags & kDNSServiceDiscoveryMoreRepliesImmediately) == 0) + [nameField reloadData]; + } + return; +} + +- (void)resolveClientWithInterface:(struct sockaddr *)interface address:(struct sockaddr *)address txtRecord:(NSString *)txtRecord +{ + if (address->sa_family != AF_INET) return; // For now we only handle IPv4 + //printf("interface length = %d, port = %d, family = %d, address = %s\n", ((struct sockaddr_in *)interface)->sin_len, ((struct sockaddr_in *)interface)->sin_port, ((struct sockaddr_in *)interface)->sin_family, inet_ntoa(((struct in_addr)((struct sockaddr_in *)interface)->sin_addr))); + //printf("address length = %d, port = %d, family = %d, address = %s\n", ((struct sockaddr_in *)address)->sin_len, ((struct sockaddr_in *)address)->sin_port, ((struct sockaddr_in *)address)->sin_family, inet_ntoa(((struct in_addr)((struct sockaddr_in *)address)->sin_addr))); + NSString *ipAddr = [NSString stringWithCString:inet_ntoa(((struct in_addr)((struct sockaddr_in *)address)->sin_addr))]; + int port = ((struct sockaddr_in *)address)->sin_port; + + [ipAddressField setStringValue:ipAddr]; + [portField setIntValue:port]; + [textField setStringValue:txtRecord]; + + return; +} + +- (void)connect:(id)sender +{ + NSString *ipAddr = [ipAddressField stringValue]; + int port = [portField intValue]; + NSString *txtRecord = [textField stringValue]; + + if (!txtRecord) txtRecord = @""; + + if (!ipAddr || !port) return; + + if ([SrvType isEqualToString:@"_ftp._tcp."]) [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"ftp://%@:%d/", ipAddr, port]]]; + else if ([SrvType isEqualToString:@"_tftp._tcp."]) [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"tftp://%@:%d/", ipAddr, port]]]; + else if ([SrvType isEqualToString:@"_ssh._tcp."]) [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"ssh://%@:%d/", ipAddr, port]]]; + else if ([SrvType isEqualToString:@"_telnet._tcp."]) [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"telnet://%@:%d/", ipAddr, port]]]; + else if ([SrvType isEqualToString:@"_http._tcp."]) [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@:%d", ipAddr, port]]]; + else if ([SrvType isEqualToString:@"_printer._tcp."]) [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"lpr://%@:%d/", ipAddr, port]]]; + else if ([SrvType isEqualToString:@"_ipp._tcp."]) [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"ipp://%@:%d/", ipAddr, port]]]; + else if ([SrvType isEqualToString:@"_afpovertcp._tcp."]) [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"afp://%@:%d/", ipAddr, port]]]; + else if ([SrvType isEqualToString:@"_smb._tcp."]) [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"smb://%@:%d/", ipAddr, port]]]; + + return; +} + +- (IBAction)handleTableClick:(id)sender +{ + //populate the text fields +} + +- (IBAction)removeSelected:(id)sender +{ + // remove the selected row and force a refresh + + int selectedRow = [serviceDisplayTable selectedRow]; + + if (selectedRow) { + + [srvtypeKeys removeObjectAtIndex:selectedRow]; + [srvnameKeys removeObjectAtIndex:selectedRow]; + + [[NSUserDefaults standardUserDefaults] setObject:srvtypeKeys forKey:@"SrvTypeKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvnameKeys forKey:@"SrvNameKeys"]; + + [typeField reloadData]; + [serviceDisplayTable reloadData]; + } +} + +- (IBAction)addNewService:(id)sender +{ + // add new entries from the edit fields to the arrays for the defaults + + if ([[serviceTypeField stringValue] length] && [[serviceNameField stringValue] length]) { + [srvtypeKeys addObject:[serviceTypeField stringValue]]; + [srvnameKeys addObject:[serviceNameField stringValue]]; + + [[NSUserDefaults standardUserDefaults] setObject:srvtypeKeys forKey:@"SrvTypeKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvnameKeys forKey:@"SrvNameKeys"]; + + [typeField reloadData]; + [serviceDisplayTable reloadData]; + } + +} + + + +@end \ No newline at end of file diff --git a/Clients/DNSServiceBrowser.nib/classes.nib b/Clients/DNSServiceBrowser.nib/classes.nib new file mode 100644 index 0000000..2668d5d --- /dev/null +++ b/Clients/DNSServiceBrowser.nib/classes.nib @@ -0,0 +1,37 @@ +{ + IBClasses = ( + { + ACTIONS = { + addNewService = id; + connect = id; + editDomains = id; + handleDomainClick = id; + handleNameClick = id; + handleTableClick = id; + handleTypeClick = id; + loadDomains = id; + removeSelected = id; + }; + CLASS = BrowserController; + LANGUAGE = ObjC; + OUTLETS = { + domainEditField = id; + domainField = id; + domainWindow = id; + ipAddressField = id; + nameColumn = id; + nameField = id; + portField = id; + serviceDisplayTable = id; + serviceNameField = id; + serviceTypeField = id; + textField = id; + typeColumn = id; + typeField = id; + }; + SUPERCLASS = NSObject; + }, + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/Clients/DNSServiceBrowser.nib/info.nib b/Clients/DNSServiceBrowser.nib/info.nib new file mode 100644 index 0000000..e31cf4c --- /dev/null +++ b/Clients/DNSServiceBrowser.nib/info.nib @@ -0,0 +1,22 @@ + + + + + IBDocumentLocation + 14 102 356 240 0 0 1152 746 + IBEditorPositions + + 29 + 22 474 271 44 0 0 1152 746 + + IBFramework Version + 273.0 + IBOpenObjects + + 220 + 201 + + IBSystem Version + 6C35 + + diff --git a/Clients/DNSServiceBrowser.nib/objects.nib b/Clients/DNSServiceBrowser.nib/objects.nib new file mode 100644 index 0000000..b330188 Binary files /dev/null and b/Clients/DNSServiceBrowser.nib/objects.nib differ diff --git a/Clients/DNSServiceReg.m b/Clients/DNSServiceReg.m new file mode 100644 index 0000000..7efd864 --- /dev/null +++ b/Clients/DNSServiceReg.m @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: DNSServiceReg.m,v $ +Revision 1.13 2003/08/12 19:55:07 cheshire +Update to APSL 2.0 + + */ + +#import "RegistrationController.h" + +#include + +void reg_reply ( + int errorCode, + void *context + ) +{ + // registration reply + printf("Got a reply from the server with error %d\n", errorCode); + return; +} + +void +MyHandleMachMessage ( CFMachPortRef port, void * msg, CFIndex size, void * info ) +{ + DNSServiceDiscovery_handleReply(msg); +} + +@implementation RegistrationController + +- (void)registerDefaults +{ + NSMutableDictionary *regDict = [NSMutableDictionary dictionary]; + + NSArray *typeArray = [NSArray arrayWithObjects:@"_ftp._tcp.", @"_ssh._tcp.", @"_tftp._tcp.", @"_http._tcp.", @"_printer._tcp.", @"_afpovertcp._tcp.", nil]; + NSArray *nameArray = [NSArray arrayWithObjects:@"My ftp Server", @"My Computer", @"Testing Boot Image", @"A Web Server", @"SteveÕs Printer", @"Company AppleShare Server", nil]; + NSArray *portArray = [NSArray arrayWithObjects:@"21", @"22", @"69", @"80", @"515", @"548", nil]; + NSArray *domainArray = [NSArray arrayWithObjects:@"", @"", @"", @"", @"", @"", nil]; + NSArray *textArray = [NSArray arrayWithObjects:@"", @"", @"image=mybootimage", @"path=/index.html", @"rn=lpt1", @"Vol=Public", nil]; + + [regDict setObject:typeArray forKey:@"SrvTypeKeys"]; + [regDict setObject:nameArray forKey:@"SrvNameKeys"]; + [regDict setObject:portArray forKey:@"SrvPortKeys"]; + [regDict setObject:domainArray forKey:@"SrvDomainKeys"]; + [regDict setObject:textArray forKey:@"SrvTextKeys"]; + + [[NSUserDefaults standardUserDefaults] registerDefaults:regDict]; +} + +- (id)init +{ + srvtypeKeys = [[NSMutableArray array] retain]; //Define arrays for Type, Domain, and Name + srvnameKeys = [[NSMutableArray array] retain]; + srvportKeys = [[NSMutableArray array] retain]; + srvdomainKeys = [[NSMutableArray array] retain]; + srvtextKeys = [[NSMutableArray array] retain]; + + registeredDict = [[NSMutableDictionary alloc] init]; + + [self registerDefaults]; + return [super init]; +} + +- (void)awakeFromNib //BrowserController startup procedure +{ + [srvtypeKeys addObjectsFromArray:[[NSUserDefaults standardUserDefaults] arrayForKey:@"SrvTypeKeys"]]; + [srvnameKeys addObjectsFromArray:[[NSUserDefaults standardUserDefaults] arrayForKey:@"SrvNameKeys"]]; + [srvportKeys addObjectsFromArray:[[NSUserDefaults standardUserDefaults] arrayForKey:@"SrvPortKeys"]]; + [srvdomainKeys addObjectsFromArray:[[NSUserDefaults standardUserDefaults] arrayForKey:@"SrvDomainKeys"]]; + [srvtextKeys addObjectsFromArray:[[NSUserDefaults standardUserDefaults] arrayForKey:@"SrvTextKeys"]]; + + [serviceDisplayTable reloadData]; //Reload (redraw) data in fields + +} + + + + - (IBAction)registerService:(id)sender +{ + int selectedRow = [serviceDisplayTable selectedRow]; + CFRunLoopSourceRef rls; + uint16_t registerPort; + CFMachPortRef cfMachPort; + CFMachPortContext context; + Boolean shouldFreeInfo; + dns_service_discovery_ref dns_client; + mach_port_t port; + + if (selectedRow < 0) { + return; + } + + context.version = 1; + context.info = 0; + context.retain = NULL; + context.release = NULL; + context.copyDescription = NULL; + + registerPort = [[srvportKeys objectAtIndex:selectedRow] intValue]; + + dns_client = DNSServiceRegistrationCreate + ( + [[srvnameKeys objectAtIndex:selectedRow] UTF8String], + [[srvtypeKeys objectAtIndex:selectedRow] UTF8String], + [[srvdomainKeys objectAtIndex:selectedRow] UTF8String], + registerPort, + [[srvtextKeys objectAtIndex:selectedRow] UTF8String], + reg_reply, + nil + ); + + port = DNSServiceDiscoveryMachPort(dns_client); + + if (port) { + + //printf("port is %d\n", port); + + cfMachPort = CFMachPortCreateWithPort ( kCFAllocatorDefault, port, ( CFMachPortCallBack ) MyHandleMachMessage,&context,&shouldFreeInfo ); + + rls = CFMachPortCreateRunLoopSource(NULL, cfMachPort, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); + CFRelease(rls); + [registeredDict setObject:[NSNumber numberWithUnsignedInt:(unsigned int)dns_client] forKey:[srvtypeKeys objectAtIndex:selectedRow]]; + } else { + printf("Could not obtain client port\n"); + } + +} + +- (IBAction)unregisterService:(id)sender +{ + int selectedRow = [serviceDisplayTable selectedRow]; + NSString *key = [srvtypeKeys objectAtIndex:selectedRow]; + + NSNumber *refPtr = [registeredDict objectForKey:key]; + dns_service_discovery_ref ref = (dns_service_discovery_ref)[refPtr unsignedIntValue]; + + if (ref) { + DNSServiceDiscoveryDeallocate(ref); + [registeredDict removeObjectForKey:key]; + } +} + +-(void)tableView:(NSTableView *)theTableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(int)row +{ + if (row<0) return; +} + +- (int)numberOfRowsInTableView:(NSTableView *)theTableView //Begin mandatory TableView methods +{ + return [srvtypeKeys count]; +} + +- (id)tableView:(NSTableView *)theTableView objectValueForTableColumn:(NSTableColumn *)theColumn row:(int)rowIndex +{ + if (theColumn == typeColumn) { + return [srvtypeKeys objectAtIndex:rowIndex]; + } + if (theColumn == nameColumn) { + return [srvnameKeys objectAtIndex:rowIndex]; + } + if (theColumn == portColumn) { + return [srvportKeys objectAtIndex:rowIndex]; + } + if (theColumn == domainColumn) { + return [srvdomainKeys objectAtIndex:rowIndex]; + } + if (theColumn == textColumn) { + return [srvtextKeys objectAtIndex:rowIndex]; + } + + return(0); +} //End of mandatory TableView methods + +- (IBAction)removeSelected:(id)sender +{ + // remove the selected row and force a refresh + + int selectedRow = [serviceDisplayTable selectedRow]; + + if (selectedRow) { + + [srvtypeKeys removeObjectAtIndex:selectedRow]; + [srvnameKeys removeObjectAtIndex:selectedRow]; + [srvportKeys removeObjectAtIndex:selectedRow]; + [srvdomainKeys removeObjectAtIndex:selectedRow]; + [srvtextKeys removeObjectAtIndex:selectedRow]; + + [[NSUserDefaults standardUserDefaults] setObject:srvtypeKeys forKey:@"SrvTypeKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvnameKeys forKey:@"SrvNameKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvportKeys forKey:@"SrvPortKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvdomainKeys forKey:@"SrvDomainKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvtextKeys forKey:@"SrvTextKeys"]; + + [serviceDisplayTable reloadData]; + } +} + +- (IBAction)addNewService:(id)sender +{ + // add new entries from the edit fields to the arrays for the defaults + + if ([[serviceTypeField stringValue] length] && [[serviceNameField stringValue] length] && [[serviceDomainField stringValue] length]&& [[servicePortField stringValue] length]) { + [srvtypeKeys addObject:[serviceTypeField stringValue]]; + [srvnameKeys addObject:[serviceNameField stringValue]]; + [srvportKeys addObject:[servicePortField stringValue]]; + [srvdomainKeys addObject:[serviceDomainField stringValue]]; + [srvtextKeys addObject:[serviceTextField stringValue]]; + + [[NSUserDefaults standardUserDefaults] setObject:srvtypeKeys forKey:@"SrvTypeKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvnameKeys forKey:@"SrvNameKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvportKeys forKey:@"SrvPortKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvdomainKeys forKey:@"SrvDomainKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvtextKeys forKey:@"SrvTextKeys"]; + + [serviceDisplayTable reloadData]; + } else { + NSBeep(); + } + +} + + + +@end diff --git a/Clients/DNSServiceReg.nib/classes.nib b/Clients/DNSServiceReg.nib/classes.nib new file mode 100644 index 0000000..46f466c --- /dev/null +++ b/Clients/DNSServiceReg.nib/classes.nib @@ -0,0 +1,30 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = { + addNewService = id; + registerService = id; + removeSelected = id; + unregisterService = id; + }; + CLASS = RegistrationController; + LANGUAGE = ObjC; + OUTLETS = { + domainColumn = NSTableColumn; + nameColumn = NSTableColumn; + portColumn = NSTableColumn; + serviceDisplayTable = NSTableView; + serviceDomainField = NSTextField; + serviceNameField = NSTextField; + servicePortField = NSTextField; + serviceTextField = NSTextField; + serviceTypeField = NSTextField; + textColumn = NSTableColumn; + typeColumn = NSTableColumn; + }; + SUPERCLASS = NSObject; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/Clients/DNSServiceReg.nib/info.nib b/Clients/DNSServiceReg.nib/info.nib new file mode 100644 index 0000000..9d2eb74 --- /dev/null +++ b/Clients/DNSServiceReg.nib/info.nib @@ -0,0 +1,22 @@ + + + + + IBDocumentLocation + 32 111 356 240 0 0 1152 746 + IBEditorPositions + + 29 + 103 609 252 44 0 0 1152 746 + + IBFramework Version + 273.0 + IBOpenObjects + + 243 + 21 + + IBSystem Version + 6C30 + + diff --git a/Clients/DNSServiceReg.nib/objects.nib b/Clients/DNSServiceReg.nib/objects.nib new file mode 100644 index 0000000..705e77d Binary files /dev/null and b/Clients/DNSServiceReg.nib/objects.nib differ diff --git a/Clients/DNSServiceRegistration.m b/Clients/DNSServiceRegistration.m new file mode 100644 index 0000000..d58de3c --- /dev/null +++ b/Clients/DNSServiceRegistration.m @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: DNSServiceRegistration.m,v $ +Revision 1.13 2003/08/12 19:55:07 cheshire +Update to APSL 2.0 + + */ + +#import "RegistrationController.h" + +#include + +void reg_reply ( + int errorCode, + void *context + ) +{ + // registration reply + printf("Got a reply from the server with error %d\n", errorCode); + return; +} + +void +MyHandleMachMessage ( CFMachPortRef port, void * msg, CFIndex size, void * info ) +{ + DNSServiceDiscovery_handleReply(msg); +} + +@implementation RegistrationController + +- (void)registerDefaults +{ + NSMutableDictionary *regDict = [NSMutableDictionary dictionary]; + + NSArray *typeArray = [NSArray arrayWithObjects:@"_ftp._tcp.", @"_ssh._tcp.", @"_tftp._tcp.", @"_http._tcp.", @"_printer._tcp.", @"_afpovertcp._tcp.", nil]; + NSArray *nameArray = [NSArray arrayWithObjects:@"My ftp Server", @"My Computer", @"Testing Boot Image", @"A Web Server", @"SteveÕs Printer", @"Company AppleShare Server", nil]; + NSArray *portArray = [NSArray arrayWithObjects:@"21", @"22", @"69", @"80", @"515", @"548", nil]; + NSArray *domainArray = [NSArray arrayWithObjects:@"", @"", @"", @"", @"", @"", nil]; + NSArray *textArray = [NSArray arrayWithObjects:@"", @"", @"image=mybootimage", @"path=/index.html", @"rn=lpt1", @"Vol=Public", nil]; + + [regDict setObject:typeArray forKey:@"SrvTypeKeys"]; + [regDict setObject:nameArray forKey:@"SrvNameKeys"]; + [regDict setObject:portArray forKey:@"SrvPortKeys"]; + [regDict setObject:domainArray forKey:@"SrvDomainKeys"]; + [regDict setObject:textArray forKey:@"SrvTextKeys"]; + + [[NSUserDefaults standardUserDefaults] registerDefaults:regDict]; +} + +- (id)init +{ + srvtypeKeys = [[NSMutableArray array] retain]; //Define arrays for Type, Domain, and Name + srvnameKeys = [[NSMutableArray array] retain]; + srvportKeys = [[NSMutableArray array] retain]; + srvdomainKeys = [[NSMutableArray array] retain]; + srvtextKeys = [[NSMutableArray array] retain]; + + registeredDict = [[NSMutableDictionary alloc] init]; + + [self registerDefaults]; + return [super init]; +} + +- (void)awakeFromNib //BrowserController startup procedure +{ + [srvtypeKeys addObjectsFromArray:[[NSUserDefaults standardUserDefaults] arrayForKey:@"SrvTypeKeys"]]; + [srvnameKeys addObjectsFromArray:[[NSUserDefaults standardUserDefaults] arrayForKey:@"SrvNameKeys"]]; + [srvportKeys addObjectsFromArray:[[NSUserDefaults standardUserDefaults] arrayForKey:@"SrvPortKeys"]]; + [srvdomainKeys addObjectsFromArray:[[NSUserDefaults standardUserDefaults] arrayForKey:@"SrvDomainKeys"]]; + [srvtextKeys addObjectsFromArray:[[NSUserDefaults standardUserDefaults] arrayForKey:@"SrvTextKeys"]]; + + [serviceDisplayTable reloadData]; //Reload (redraw) data in fields + +} + + + + - (IBAction)registerService:(id)sender +{ + int selectedRow = [serviceDisplayTable selectedRow]; + CFRunLoopSourceRef rls; + uint16_t registerPort; + CFMachPortRef cfMachPort; + CFMachPortContext context; + Boolean shouldFreeInfo; + dns_service_discovery_ref dns_client; + mach_port_t port; + + if (selectedRow < 0) { + return; + } + + context.version = 1; + context.info = 0; + context.retain = NULL; + context.release = NULL; + context.copyDescription = NULL; + + registerPort = [[srvportKeys objectAtIndex:selectedRow] intValue]; + + dns_client = DNSServiceRegistrationCreate + ( + [[srvnameKeys objectAtIndex:selectedRow] UTF8String], + [[srvtypeKeys objectAtIndex:selectedRow] UTF8String], + [[srvdomainKeys objectAtIndex:selectedRow] UTF8String], + registerPort, + [[srvtextKeys objectAtIndex:selectedRow] UTF8String], + reg_reply, + nil + ); + + port = DNSServiceDiscoveryMachPort(dns_client); + + if (port) { + + //printf("port is %d\n", port); + + cfMachPort = CFMachPortCreateWithPort ( kCFAllocatorDefault, port, ( CFMachPortCallBack ) MyHandleMachMessage,&context,&shouldFreeInfo ); + + rls = CFMachPortCreateRunLoopSource(NULL, cfMachPort, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); + CFRelease(rls); + [registeredDict setObject:[NSNumber numberWithUnsignedInt:(unsigned int)dns_client] forKey:[srvtypeKeys objectAtIndex:selectedRow]]; + } else { + printf("Could not obtain client port\n"); + } + +} + +- (IBAction)unregisterService:(id)sender +{ + int selectedRow = [serviceDisplayTable selectedRow]; + NSString *key = [srvtypeKeys objectAtIndex:selectedRow]; + + NSNumber *refPtr = [registeredDict objectForKey:key]; + dns_service_discovery_ref ref = (dns_service_discovery_ref)[refPtr unsignedIntValue]; + + if (ref) { + DNSServiceDiscoveryDeallocate(ref); + [registeredDict removeObjectForKey:key]; + } +} + +-(void)tableView:(NSTableView *)theTableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(int)row +{ + if (row<0) return; +} + +- (int)numberOfRowsInTableView:(NSTableView *)theTableView //Begin mandatory TableView methods +{ + return [srvtypeKeys count]; +} + +- (id)tableView:(NSTableView *)theTableView objectValueForTableColumn:(NSTableColumn *)theColumn row:(int)rowIndex +{ + if (theColumn == typeColumn) { + return [srvtypeKeys objectAtIndex:rowIndex]; + } + if (theColumn == nameColumn) { + return [srvnameKeys objectAtIndex:rowIndex]; + } + if (theColumn == portColumn) { + return [srvportKeys objectAtIndex:rowIndex]; + } + if (theColumn == domainColumn) { + return [srvdomainKeys objectAtIndex:rowIndex]; + } + if (theColumn == textColumn) { + return [srvtextKeys objectAtIndex:rowIndex]; + } + + return(0); +} //End of mandatory TableView methods + +- (IBAction)removeSelected:(id)sender +{ + // remove the selected row and force a refresh + + int selectedRow = [serviceDisplayTable selectedRow]; + + if (selectedRow) { + + [srvtypeKeys removeObjectAtIndex:selectedRow]; + [srvnameKeys removeObjectAtIndex:selectedRow]; + [srvportKeys removeObjectAtIndex:selectedRow]; + [srvdomainKeys removeObjectAtIndex:selectedRow]; + [srvtextKeys removeObjectAtIndex:selectedRow]; + + [[NSUserDefaults standardUserDefaults] setObject:srvtypeKeys forKey:@"SrvTypeKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvnameKeys forKey:@"SrvNameKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvportKeys forKey:@"SrvPortKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvdomainKeys forKey:@"SrvDomainKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvtextKeys forKey:@"SrvTextKeys"]; + + [serviceDisplayTable reloadData]; + } +} + +- (IBAction)addNewService:(id)sender +{ + // add new entries from the edit fields to the arrays for the defaults + + if ([[serviceTypeField stringValue] length] && [[serviceNameField stringValue] length] && [[serviceDomainField stringValue] length]&& [[servicePortField stringValue] length]) { + [srvtypeKeys addObject:[serviceTypeField stringValue]]; + [srvnameKeys addObject:[serviceNameField stringValue]]; + [srvportKeys addObject:[servicePortField stringValue]]; + [srvdomainKeys addObject:[serviceDomainField stringValue]]; + [srvtextKeys addObject:[serviceTextField stringValue]]; + + [[NSUserDefaults standardUserDefaults] setObject:srvtypeKeys forKey:@"SrvTypeKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvnameKeys forKey:@"SrvNameKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvportKeys forKey:@"SrvPortKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvdomainKeys forKey:@"SrvDomainKeys"]; + [[NSUserDefaults standardUserDefaults] setObject:srvtextKeys forKey:@"SrvTextKeys"]; + + [serviceDisplayTable reloadData]; + } else { + NSBeep(); + } + +} + + + +@end diff --git a/Clients/DNSServiceRegistration.nib/classes.nib b/Clients/DNSServiceRegistration.nib/classes.nib new file mode 100644 index 0000000..46f466c --- /dev/null +++ b/Clients/DNSServiceRegistration.nib/classes.nib @@ -0,0 +1,30 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = { + addNewService = id; + registerService = id; + removeSelected = id; + unregisterService = id; + }; + CLASS = RegistrationController; + LANGUAGE = ObjC; + OUTLETS = { + domainColumn = NSTableColumn; + nameColumn = NSTableColumn; + portColumn = NSTableColumn; + serviceDisplayTable = NSTableView; + serviceDomainField = NSTextField; + serviceNameField = NSTextField; + servicePortField = NSTextField; + serviceTextField = NSTextField; + serviceTypeField = NSTextField; + textColumn = NSTableColumn; + typeColumn = NSTableColumn; + }; + SUPERCLASS = NSObject; + } + ); + IBVersion = 1; +} \ No newline at end of file diff --git a/Clients/DNSServiceRegistration.nib/info.nib b/Clients/DNSServiceRegistration.nib/info.nib new file mode 100644 index 0000000..9d2eb74 --- /dev/null +++ b/Clients/DNSServiceRegistration.nib/info.nib @@ -0,0 +1,22 @@ + + + + + IBDocumentLocation + 32 111 356 240 0 0 1152 746 + IBEditorPositions + + 29 + 103 609 252 44 0 0 1152 746 + + IBFramework Version + 273.0 + IBOpenObjects + + 243 + 21 + + IBSystem Version + 6C30 + + diff --git a/Clients/DNSServiceRegistration.nib/objects.nib b/Clients/DNSServiceRegistration.nib/objects.nib new file mode 100644 index 0000000..705e77d Binary files /dev/null and b/Clients/DNSServiceRegistration.nib/objects.nib differ diff --git a/Makefile b/Makefile index 9e1478f..e6dbb70 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ include /Developer/Makefiles/pb_makefiles/platform.make -MVERS = "mDNSResponder-58.8" +MVERS = "mDNSResponder-58.8.1" install: cd "$(SRCROOT)/mDNSMacOSX"; pbxbuild install OBJROOT=$(OBJROOT) SYMROOT=$(SYMROOT) DSTROOT=$(DSTROOT) MVERS=$(MVERS) diff --git a/mDNSCore/mDNS.c b/mDNSCore/mDNS.c index 229df34..556bdd1 100755 --- a/mDNSCore/mDNS.c +++ b/mDNSCore/mDNS.c @@ -44,6 +44,23 @@ Change History (most recent first): $Log: mDNS.c,v $ +Revision 1.307.2.13 2005/01/28 05:39:12 cheshire +Remove LogMsg() + +Revision 1.307.2.12 2005/01/28 05:02:05 cheshire + SUPan: Replace IP TTL 255 check with local-subnet check + +Revision 1.307.2.11 2005/01/28 04:03:23 cheshire + SUPan: Current method of doing subtypes causes name collisions +Summary: Pulled in ConstructServiceName, CountSubTypes and AllocateSubTypes from Tiger version. + +Revision 1.307.2.10 2004/06/18 17:28:18 cheshire + Current method of doing subtypes causes name collisions + +Revision 1.307.2.9 2004/06/18 00:31:51 cheshire + mDNSResponder escape handling inconsistent with BIND +(Prerequisite for fixing ) + Revision 1.307.2.8 2004/04/03 05:18:19 bradley Added cast to fix signed/unsigned warning due to int promotion. @@ -987,7 +1004,7 @@ Revision 1.61 2002/09/20 01:05:24 cheshire Don't kill the Extras list in mDNS_DeregisterService() Revision 1.60 2002/09/19 23:47:35 cheshire -Added mDNS_RegisterNoSuchService() function for assertion of non-existance +Added mDNS_RegisterNoSuchService() function for assertion of non-existence of a particular named service Revision 1.59 2002/09/19 21:25:34 cheshire @@ -1481,7 +1498,7 @@ mDNSexport mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2) return(mDNSfalse); } -mDNSlocal mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip) +mDNSexport mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip) { switch(ip->type) { @@ -1647,15 +1664,14 @@ mDNSexport mDNSu8 *AppendDNSNameString(domainname *const name, const char *cstr) mDNSu8 c = (mDNSu8)*cstr++; // Read the character if (c == '\\') // If escape character, check next character { - if (*cstr == '\\' || *cstr == '.') // If a second escape, or a dot, - c = (mDNSu8)*cstr++; // just use the second character - else if (mdnsIsDigit(cstr[0]) && mdnsIsDigit(cstr[1]) && mdnsIsDigit(cstr[2])) - { // else, if three decimal digits, - int v0 = cstr[0] - '0'; // then interpret as three-digit decimal - int v1 = cstr[1] - '0'; - int v2 = cstr[2] - '0'; + c = (mDNSu8)*cstr++; // Assume we'll just take the next character + if (mdnsIsDigit(cstr[-1]) && mdnsIsDigit(cstr[0]) && mdnsIsDigit(cstr[1])) + { // If three decimal digits, + int v0 = cstr[-1] - '0'; // then interpret as three-digit decimal + int v1 = cstr[ 0] - '0'; + int v2 = cstr[ 1] - '0'; int val = v0 * 100 + v1 * 10 + v2; - if (val <= 255) { c = (mDNSu8)val; cstr += 3; } // If valid value, use it + if (val <= 255) { c = (mDNSu8)val; cstr += 2; } // If valid three-digit decimal value, use it } } *ptr++ = c; // Write the character @@ -1828,15 +1844,31 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn, // In the case where there is no name (and ONLY in that case), // a single-label subtype is allowed as the first label of a three-part "type" - if (!name) + if (!name && type) { - const mDNSu8 *s2 = type->c + 1 + type->c[0]; - if (type->c[0] > 0 && type->c[0] < 0x40 && - s2[0] > 0 && s2[0] < 0x40 && - s2[1+s2[0]] > 0 && s2[1+s2[0]] < 0x40) + const mDNSu8 *s0 = type->c; + if (s0[0] && s0[0] < 0x40) // If legal first label (at least one character, and no more than 63) { - name = (domainlabel *)type; - type = (domainname *)s2; + const mDNSu8 * s1 = s0 + 1 + s0[0]; + if (s1[0] && s1[0] < 0x40) // and legal second label (at least one character, and no more than 63) + { + const mDNSu8 *s2 = s1 + 1 + s1[0]; + if (s2[0] && s2[0] < 0x40 && s2[1+s2[0]] == 0) // and we have three and only three labels + { + static const mDNSu8 SubTypeLabel[5] = "\x04_sub"; + src = s0; // Copy the first label + len = *src; + for (i=0; i <= len; i++) *dst++ = *src++; + for (i=0; i < (int)sizeof(SubTypeLabel); i++) *dst++ = SubTypeLabel[i]; + type = (domainname *)s1; + + // Special support for queries done by older versions of "Rendezvous Browser" + // For these queries, we retract the "._sub" we just added between the subtype and the main type + if (SameDomainName((domainname*)s0, (domainname*)"\x09_services\x07_dns-sd\x04_udp") || + SameDomainName((domainname*)s0, (domainname*)"\x09_services\x05_mdns\x04_udp")) + dst -= sizeof(SubTypeLabel); + } + } } } @@ -1849,26 +1881,29 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn, } else name = (domainlabel*)""; // Set this up to be non-null, to avoid errors if we have to call LogMsg() below - + src = type->c; // Put the service type into the domain name len = *src; - if (len < 2 || len >= 0x40) { errormsg="Invalid service application protocol name"; goto fail; } - if (src[1] != '_') { errormsg="Service application protocol name must begin with underscore"; goto fail; } + if (len < 2 || len >= 0x40 || (len > 15 && !SameDomainName(domain, (domainname*)"\x05" "local"))) + { + errormsg="Application protocol name must be underscore plus 1-14 characters. See "; + goto fail; + } + if (src[1] != '_') { errormsg="Application protocol name must begin with underscore"; goto fail; } for (i=2; i<=len; i++) if (!mdnsIsLetter(src[i]) && !mdnsIsDigit(src[i]) && src[i] != '-' && src[i] != '_') - { errormsg="Service application protocol name must contain only letters, digits, and hyphens"; goto fail; } + { errormsg="Application protocol name must contain only letters, digits, and hyphens"; goto fail; } for (i=0; i<=len; i++) *dst++ = *src++; len = *src; - //if (len == 0 || len >= 0x40) { errormsg="Invalid service transport protocol name"; goto fail; } if (!(len == 4 && src[1] == '_' && (((src[2] | 0x20) == 'u' && (src[3] | 0x20) == 'd') || ((src[2] | 0x20) == 't' && (src[3] | 0x20) == 'c')) && (src[4] | 0x20) == 'p')) - { errormsg="Service transport protocol name must be _udp or _tcp"; goto fail; } + { errormsg="Transport protocol name must be _udp or _tcp"; goto fail; } for (i=0; i<=len; i++) *dst++ = *src++; - + if (*src) { errormsg="Service type must have only two labels"; goto fail; } - + *dst = 0; dst = AppendDomainName(fqdn, domain); if (!dst) { errormsg="Service domain too long"; goto fail; } @@ -5360,33 +5395,64 @@ exit: return(responseptr); } +mDNSlocal mDNSBool AddressIsLocalSubnet(mDNS *const m, const mDNSInterfaceID InterfaceID, const mDNSAddr *addr) + { + NetworkInterfaceInfo *intf; + + if (addr->type == mDNSAddrType_IPv4) + { + if (addr->ip.v4.b[0] == 169 && addr->ip.v4.b[1] == 254) return(mDNStrue); + for (intf = m->HostInterfaces; intf; intf = intf->next) + if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID) + if (((intf->ip.ip.v4.NotAnInteger ^ addr->ip.v4.NotAnInteger) & intf->mask.ip.v4.NotAnInteger) == 0) + return(mDNStrue); + } + + if (addr->type == mDNSAddrType_IPv6) + { + if (addr->ip.v6.b[0] == 0xFE && addr->ip.v6.b[1] == 0x80) return(mDNStrue); + for (intf = m->HostInterfaces; intf; intf = intf->next) + if (intf->ip.type == addr->type && intf->InterfaceID == InterfaceID) + if ((((intf->ip.ip.v6.l[0] ^ addr->ip.v6.l[0]) & intf->mask.ip.v6.l[0]) == 0) && + (((intf->ip.ip.v6.l[1] ^ addr->ip.v6.l[1]) & intf->mask.ip.v6.l[1]) == 0) && + (((intf->ip.ip.v6.l[2] ^ addr->ip.v6.l[2]) & intf->mask.ip.v6.l[2]) == 0) && + (((intf->ip.ip.v6.l[3] ^ addr->ip.v6.l[3]) & intf->mask.ip.v6.l[3]) == 0)) + return(mDNStrue); + } + + return(mDNSfalse); + } + mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *srcaddr, const mDNSIPPort srcport, const mDNSAddr *dstaddr, mDNSIPPort dstport, const mDNSInterfaceID InterfaceID) { - DNSMessage response; - const mDNSu8 *responseend = mDNSNULL; - - verbosedebugf("Received Query from %#-15a:%d to %#-15a:%d on 0x%.8X with %2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s", - srcaddr, (mDNSu16)srcport.b[0]<<8 | srcport.b[1], - dstaddr, (mDNSu16)dstport.b[0]<<8 | dstport.b[1], - InterfaceID, - msg->h.numQuestions, msg->h.numQuestions == 1 ? ", " : "s,", - msg->h.numAnswers, msg->h.numAnswers == 1 ? ", " : "s,", - msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y, " : "ies,", - msg->h.numAdditionals, msg->h.numAdditionals == 1 ? "" : "s"); - - responseend = ProcessQuery(m, msg, end, srcaddr, InterfaceID, - (srcport.NotAnInteger != MulticastDNSPort.NotAnInteger), mDNSAddrIsDNSMulticast(dstaddr), &response); - - if (responseend) // If responseend is non-null, that means we built a unicast response packet + if (mDNSAddrIsDNSMulticast(dstaddr) || AddressIsLocalSubnet(m, InterfaceID, srcaddr)) { - debugf("Unicast Response: %d Question%s, %d Answer%s, %d Additional%s to %#-15a:%d on %p/%ld", - response.h.numQuestions, response.h.numQuestions == 1 ? "" : "s", - response.h.numAnswers, response.h.numAnswers == 1 ? "" : "s", - response.h.numAdditionals, response.h.numAdditionals == 1 ? "" : "s", - srcaddr, (mDNSu16)srcport.b[0]<<8 | srcport.b[1], InterfaceID, srcaddr->type); - mDNSSendDNSMessage(m, &response, responseend, InterfaceID, dstport, srcaddr, srcport); + DNSMessage response; + const mDNSu8 *responseend = mDNSNULL; + + verbosedebugf("Received Query from %#-15a:%d to %#-15a:%d on 0x%.8X with %2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s", + srcaddr, (mDNSu16)srcport.b[0]<<8 | srcport.b[1], + dstaddr, (mDNSu16)dstport.b[0]<<8 | dstport.b[1], + InterfaceID, + msg->h.numQuestions, msg->h.numQuestions == 1 ? ", " : "s,", + msg->h.numAnswers, msg->h.numAnswers == 1 ? ", " : "s,", + msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y, " : "ies,", + msg->h.numAdditionals, msg->h.numAdditionals == 1 ? "" : "s"); + + responseend = ProcessQuery(m, msg, end, srcaddr, InterfaceID, + (srcport.NotAnInteger != MulticastDNSPort.NotAnInteger), mDNSAddrIsDNSMulticast(dstaddr), &response); + + if (responseend) // If responseend is non-null, that means we built a unicast response packet + { + debugf("Unicast Response: %d Question%s, %d Answer%s, %d Additional%s to %#-15a:%d on %p/%ld", + response.h.numQuestions, response.h.numQuestions == 1 ? "" : "s", + response.h.numAnswers, response.h.numAnswers == 1 ? "" : "s", + response.h.numAdditionals, response.h.numAdditionals == 1 ? "" : "s", + srcaddr, (mDNSu16)srcport.b[0]<<8 | srcport.b[1], InterfaceID, srcaddr->type); + mDNSSendDNSMessage(m, &response, responseend, InterfaceID, dstport, srcaddr, srcport); + } } } @@ -5395,7 +5461,7 @@ mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg, // Any code walking either list must use the CurrentQuestion and/or CurrentRecord mechanism to protect against this. mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, const DNSMessage *const response, const mDNSu8 *end, const mDNSAddr *srcaddr, const mDNSAddr *dstaddr, - const mDNSInterfaceID InterfaceID, mDNSu8 ttl) + const mDNSInterfaceID InterfaceID) { int i; const mDNSu8 *ptr = LocateAnswers(response, end); // We ignore questions (if any) in a DNS response packet @@ -5409,28 +5475,25 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, (void)srcaddr; // Currently used only for display in debugging message - verbosedebugf("Received Response from %#-15a addressed to %#-15a on %p TTL %d with %2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s", - srcaddr, dstaddr, InterfaceID, ttl, + verbosedebugf("Received Response from %#-15a addressed to %#-15a on %p with %2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s", + srcaddr, dstaddr, InterfaceID, response->h.numQuestions, response->h.numQuestions == 1 ? ", " : "s,", response->h.numAnswers, response->h.numAnswers == 1 ? ", " : "s,", response->h.numAuthorities, response->h.numAuthorities == 1 ? "y, " : "ies,", response->h.numAdditionals, response->h.numAdditionals == 1 ? "" : "s"); - // TTL should be 255 - // In the case of overlayed subnets that aren't using RFC 3442, some packets may incorrectly - // go to the router first and then come back with a TTL of 254, so we allow that too. - // Anything lower than 254 is a pretty good sign of an off-net spoofing attack. - // Also, if we get a unicast response when we weren't expecting one, then we assume it is someone trying to spoof us - if (ttl < 254 || (!mDNSAddrIsDNSMulticast(dstaddr) && (mDNSu32)(m->timenow - m->ExpectUnicastResponse) > (mDNSu32)mDNSPlatformOneSecond)) - { - debugf("** Ignored apparent spoof mDNS Response from %#-15a to %#-15a TTL %d on %p with %2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s", - srcaddr, dstaddr, ttl, InterfaceID, - response->h.numQuestions, response->h.numQuestions == 1 ? ", " : "s,", - response->h.numAnswers, response->h.numAnswers == 1 ? ", " : "s,", - response->h.numAuthorities, response->h.numAuthorities == 1 ? "y, " : "ies,", - response->h.numAdditionals, response->h.numAdditionals == 1 ? "" : "s"); - return; - } + // If we get a unicast response when we weren't expecting one, then we assume it is someone trying to spoof us + if (!mDNSAddrIsDNSMulticast(dstaddr)) + if (!AddressIsLocalSubnet(m, InterfaceID, srcaddr) || (mDNSu32)(m->timenow - m->ExpectUnicastResponse) > (mDNSu32)(mDNSPlatformOneSecond*2)) + { + debugf("** Ignored apparent spoof mDNS Response from %#-15a to %#-15a on %p with %2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s", + srcaddr, dstaddr, InterfaceID, + response->h.numQuestions, response->h.numQuestions == 1 ? ", " : "s,", + response->h.numAnswers, response->h.numAnswers == 1 ? ", " : "s,", + response->h.numAuthorities, response->h.numAuthorities == 1 ? "y, " : "ies,", + response->h.numAdditionals, response->h.numAdditionals == 1 ? "" : "s"); + return; + } for (i = 0; i < totalrecords && ptr && ptr < end; i++) { @@ -5633,12 +5696,14 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m, mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, const mDNSAddr *const srcaddr, const mDNSIPPort srcport, const mDNSAddr *const dstaddr, const mDNSIPPort dstport, - const mDNSInterfaceID InterfaceID, mDNSu8 ttl) + const mDNSInterfaceID InterfaceID, mDNSu8 unusedttl) { const mDNSu8 StdQ = kDNSFlag0_QR_Query | kDNSFlag0_OP_StdQuery; const mDNSu8 StdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery; const mDNSu8 QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask); + (void)unusedttl; + // Read the integer parts which are in IETF byte-order (MSB first, LSB second) mDNSu8 *ptr = (mDNSu8 *)&msg->h.numQuestions; msg->h.numQuestions = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]); @@ -5654,7 +5719,7 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNS mDNS_Lock(m); if (QR_OP == StdQ) mDNSCoreReceiveQuery (m, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID); - else if (QR_OP == StdR) mDNSCoreReceiveResponse(m, msg, end, srcaddr, dstaddr, InterfaceID, ttl); + else if (QR_OP == StdR) mDNSCoreReceiveResponse(m, msg, end, srcaddr, dstaddr, InterfaceID); else debugf("Unknown DNS packet type %02X%02X (ignored)", msg->h.flags.b[0], msg->h.flags.b[1]); // Packet reception often causes a change to the task list: @@ -6611,7 +6676,7 @@ mDNSlocal void ServiceCallback(mDNS *const m, AuthRecord *const rr, mStatus resu if (result == mStatus_MemFree) { - // If the PTR record or any of the subtype PTR record are still in the process of deregistering, + // If the PTR record or any of the subtype PTR records are still in the process of deregistering, // don't pass on the NameConflict/MemFree message until every record is finished cleaning up. mDNSu32 i; if (sr->RR_PTR.resrec.RecordType != kDNSRecordTypeUnregistered) return; @@ -6688,9 +6753,12 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr, // already set the first label of the record name to the subtype being registered for (i=0; iSubTypes[i].resrec.name; + domainname st; + AssignDomainName(st, sr->SubTypes[i].resrec.name); + st.c[1+st.c[0]] = 0; // Only want the first label, not the whole FQDN (particularly for mDNS_RenameAndReregisterService()) + AppendDomainName(&st, type); mDNS_SetupResourceRecord(&sr->SubTypes[i], mDNSNULL, InterfaceID, kDNSType_PTR, kDefaultTTLforShared, kDNSRecordTypeShared, ServiceCallback, sr); - if (ConstructServiceName(&sr->SubTypes[i].resrec.name, &s, type, domain) == mDNSNULL) return(mStatus_BadParamErr); + if (ConstructServiceName(&sr->SubTypes[i].resrec.name, mDNSNULL, &st, domain) == mDNSNULL) return(mStatus_BadParamErr); AssignDomainName(sr->SubTypes[i].resrec.rdata->u.name, sr->RR_SRV.resrec.name); sr->SubTypes[i].Additional1 = &sr->RR_SRV; sr->SubTypes[i].Additional2 = &sr->RR_TXT; diff --git a/mDNSCore/mDNSClientAPI.h b/mDNSCore/mDNSClientAPI.h index cb5bace..4381c67 100755 --- a/mDNSCore/mDNSClientAPI.h +++ b/mDNSCore/mDNSClientAPI.h @@ -23,6 +23,9 @@ Change History (most recent first): $Log: mDNSClientAPI.h,v $ +Revision 1.114.2.10 2005/01/28 05:02:05 cheshire + SUPan: Replace IP TTL 255 check with local-subnet check + Revision 1.114.2.9 2004/04/22 03:17:35 cheshire Fix use of "struct __attribute__((__packed__))" so it only applies on GCC >= 2.9 @@ -404,7 +407,7 @@ Revision 1.25 2002/09/21 20:44:49 zarzycki Added APSL info Revision 1.24 2002/09/19 23:47:35 cheshire -Added mDNS_RegisterNoSuchService() function for assertion of non-existance +Added mDNS_RegisterNoSuchService() function for assertion of non-existence of a particular named service Revision 1.23 2002/09/19 21:25:34 cheshire @@ -885,6 +888,8 @@ struct NetworkInterfaceInfo_struct // Client API fields: The client must set up these fields *before* calling mDNS_RegisterInterface() mDNSInterfaceID InterfaceID; mDNSAddr ip; + mDNSAddr mask; + char ifname[16]; mDNSBool Advertise; // Set Advertise to false if you are only searching on this interface mDNSBool TxAndRx; // Set to false if not sending and receiving packets on this interface }; @@ -1336,6 +1341,7 @@ extern char *DNSTypeName(mDNSu16 rrtype); extern char *GetRRDisplayString_rdb(mDNS *const m, const ResourceRecord *rr, RDataBody *rd); #define GetRRDisplayString(m, rr) GetRRDisplayString_rdb((m), &(rr)->resrec, &(rr)->resrec.rdata->u) extern mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2); +extern mDNSBool mDNSAddrIsDNSMulticast(const mDNSAddr *ip); extern void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText); // *************************************************************************** diff --git a/mDNSCore/mDNSEmbeddedAPI.h b/mDNSCore/mDNSEmbeddedAPI.h new file mode 100755 index 0000000..3b53374 --- /dev/null +++ b/mDNSCore/mDNSEmbeddedAPI.h @@ -0,0 +1,1470 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: mDNSEmbeddedAPI.h,v $ +Revision 1.114.2.9 2004/04/22 03:17:35 cheshire +Fix use of "struct __attribute__((__packed__))" so it only applies on GCC >= 2.9 + +Revision 1.114.2.8 2004/03/30 06:55:37 cheshire +Gave name to anonymous struct, to avoid errors on certain compilers. +(Thanks to ramaprasad.kr@hp.com for reporting this.) + +Revision 1.114.2.7 2004/03/09 02:31:27 cheshire +Remove erroneous underscore in 'packed_struct' (makes no difference now, but might in future) + +Revision 1.114.2.6 2004/03/02 02:55:25 cheshire + Properly support "_services._dns-sd._udp" meta-queries + +Revision 1.114.2.5 2004/02/18 23:35:17 cheshire +: Hard code domain enumeration functions to return ".local" only +Also make mDNS_StopGetDomains() a no-op too, so that we don't get warning messages in syslog + +Revision 1.114.2.4 2004/01/28 23:29:20 cheshire +Fix structure packing (only affects third-party Darwin developers) + +Revision 1.114.2.3 2003/12/05 00:03:34 cheshire + Use buffer size MAX_ESCAPED_DOMAIN_NAME instead of 256 + +Revision 1.114.2.2 2003/12/04 23:30:00 cheshire +Add "#define MAX_ESCAPED_DOMAIN_NAME 1005", needed for Posix folder to build + +Revision 1.114.2.1 2003/12/03 11:07:58 cheshire +: Stop and start of a service uses old ip address (with old port number) + +Revision 1.114 2003/08/29 19:44:15 cheshire + Traffic reduction: Eliminate synchronized QUs when a new service appears +1. Use m->RandomQueryDelay to impose a random delay in the range 0-500ms on queries + that already have at least one unique answer in the cache +2. For these queries, go straight to QM, skipping QU + +Revision 1.113 2003/08/21 19:31:58 cheshire +Cosmetic: Swap order of fields + +Revision 1.112 2003/08/21 19:27:36 cheshire + Traffic reduction: No need to announce record for longer than TTL + +Revision 1.111 2003/08/21 02:21:50 cheshire + Efficiency: Reduce repeated queries + +Revision 1.110 2003/08/20 23:39:31 cheshire + Review syslog messages, and remove as appropriate + +Revision 1.109 2003/08/19 22:24:10 cheshire +Comment change + +Revision 1.108 2003/08/19 22:20:00 cheshire + Don't use IPv6 on interfaces that have a routable IPv4 address configured +More minor refinements + +Revision 1.107 2003/08/19 06:48:25 cheshire + Guard against excessive record updates +Each record starts with 10 UpdateCredits. +Every update consumes one UpdateCredit. +UpdateCredits are replenished at a rate of one one per minute, up to a maximum of 10. +As the number of UpdateCredits declines, the number of announcements is similarly scaled back. +When fewer than 5 UpdateCredits remain, the first announcement is also delayed by an increasing amount. + +Revision 1.106 2003/08/19 04:49:28 cheshire + Interaction between v4, v6 and dual-stack hosts not working quite right +1. A dual-stack host should only suppress its own query if it sees the same query from other hosts on BOTH IPv4 and IPv6. +2. When we see the first v4 (or first v6) member of a group, we re-trigger questions and probes on that interface. +3. When we see the last v4 (or v6) member of a group go away, we revalidate all the records received on that interface. + +Revision 1.105 2003/08/19 02:33:37 cheshire +Update comments + +Revision 1.104 2003/08/19 02:31:11 cheshire + mDNSResponder overenthusiastic with final expiration queries +Final expiration queries now only mark the question for sending on the particular interface +pertaining to the record that's expiring. + +Revision 1.103 2003/08/18 19:05:44 cheshire + UpdateRecord not working right +Added "newrdlength" field to hold new length of updated rdata + +Revision 1.102 2003/08/16 03:39:00 cheshire + InterfaceID -1 indicates "local only" + +Revision 1.101 2003/08/15 20:16:02 cheshire + mDNSResponder takes too much RPRVT +We want to avoid touching the rdata pages, so we don't page them in. +1. RDLength was stored with the rdata, which meant touching the page just to find the length. + Moved this from the RData to the ResourceRecord object. +2. To avoid unnecessarily touching the rdata just to compare it, + compute a hash of the rdata and store the hash in the ResourceRecord object. + +Revision 1.100 2003/08/14 19:29:04 cheshire + Include cache records in SIGINFO output +Moved declarations of DNSTypeName() and GetRRDisplayString to mDNSEmbeddedAPI.h so daemon.c can use them + +Revision 1.99 2003/08/14 02:17:05 cheshire + Split generic ResourceRecord type into two separate types: AuthRecord and CacheRecord + +Revision 1.98 2003/08/12 19:56:23 cheshire +Update to APSL 2.0 + +Revision 1.97 2003/08/12 14:59:27 cheshire + Rate-limiting blocks some legitimate responses +When setting LastMCTime also record LastMCInterface. When checking LastMCTime to determine +whether to suppress the response, also check LastMCInterface to see if it matches. + +Revision 1.96 2003/08/12 13:57:04 cheshire + Improve cache performance +Changed the number of hash table slots from 37 to 499 + +Revision 1.95 2003/08/09 00:55:02 cheshire + mDNSResponder is taking 20-30% of the CPU +Don't scan the whole cache after every packet. + +Revision 1.94 2003/08/09 00:35:29 cheshire + +Revision 1.93 2003/08/08 18:55:48 cheshire + Guard against time going backwards + +Revision 1.92 2003/08/08 18:36:04 cheshire + Only need to revalidate on interface removal on platforms that have the PhantomInterfaces bug + +Revision 1.91 2003/08/06 21:33:39 cheshire +Fix compiler warnings on PocketPC 2003 (Windows CE) + +Revision 1.90 2003/08/06 20:30:17 cheshire +Add structure definition for rdataMX (not currently used, but good to have it for completeness) + +Revision 1.89 2003/08/06 18:58:19 cheshire +Update comments + +Revision 1.88 2003/07/24 23:45:44 cheshire +To eliminate compiler warnings, changed definition of mDNSBool from +"unsigned char" to "int", since "int" is in fact truly the type that C uses +for the result of comparison operators (a: Feature: New Rendezvous APIs (#7875) (mDNSResponder component) +Added error type for incompatibility between daemon and client versions + +Revision 1.85 2003/07/19 03:23:13 cheshire + mDNSResponder needs to receive and cache larger records + +Revision 1.84 2003/07/18 23:52:12 cheshire +To improve consistency of field naming, global search-and-replace: +NextProbeTime -> NextScheduledProbe +NextResponseTime -> NextScheduledResponse + +Revision 1.83 2003/07/18 00:29:59 cheshire + Remove mDNSResponder version from packet header and use HINFO record instead + +Revision 1.82 2003/07/17 17:35:04 cheshire + Rate-limit responses, to guard against packet flooding + +Revision 1.81 2003/07/16 05:01:36 cheshire +Add fields 'LargeAnswers' and 'ExpectUnicastResponse' in preparation for + Need to implement "unicast response" request, using top bit of qclass + +Revision 1.80 2003/07/15 01:55:12 cheshire + Need to implement service registration with subtypes + +Revision 1.79 2003/07/13 02:28:00 cheshire + SendResponses didn't all its responses +Delete all references to RRInterfaceActive -- it's now superfluous + +Revision 1.78 2003/07/13 01:47:53 cheshire +Fix one error and one warning in the Windows build + +Revision 1.77 2003/07/11 01:32:38 cheshire +Syntactic cleanup (no change to funcationality): Now that we only have one host name, +rename field "hostname1" to "hostname", and field "RR_A1" to "RR_A". + +Revision 1.76 2003/07/11 01:28:00 cheshire + No more local.arpa + +Revision 1.75 2003/07/02 21:19:45 cheshire + Update copyright notices, etc., in source code comments + +Revision 1.74 2003/07/02 02:41:23 cheshire + mDNSResponder needs to start with a smaller cache and then grow it as needed + +Revision 1.73 2003/06/10 04:24:39 cheshire + React when we observe other people query unsuccessfully for a record that's in our cache +Some additional refinements: +Don't try to do this for unicast-response queries +better tracking of Qs and KAs in multi-packet KA lists + +Revision 1.72 2003/06/10 01:46:27 cheshire +Add better comments explaining how these data structures are intended to be used from the client layer + +Revision 1.71 2003/06/07 06:45:05 cheshire + No need for multiple machines to all be sending the same queries + +Revision 1.70 2003/06/07 04:50:53 cheshire + React when we observe other people query unsuccessfully for a record that's in our cache + +Revision 1.69 2003/06/07 04:22:17 cheshire +Add MsgBuffer for error log and debug messages + +Revision 1.68 2003/06/07 01:46:38 cheshire + When query produces zero results, call mDNS_Reconfirm() on any antecedent records + +Revision 1.67 2003/06/07 01:22:14 cheshire + mDNSResponder needs an mDNS_Reconfirm() function + +Revision 1.66 2003/06/07 00:59:43 cheshire + Need some randomness to spread queries on the network + +Revision 1.65 2003/06/06 21:41:11 cheshire +For consistency, mDNS_StopQuery() should return an mStatus result, just like all the other mDNSCore routines + +Revision 1.64 2003/06/06 21:38:55 cheshire +Renamed 'NewData' as 'FreshData' (The data may not be new data, just a refresh of data that we +already had in our cache. This refreshes our TTL on the data, but the data itself stays the same.) + +Revision 1.63 2003/06/06 17:20:14 cheshire +For clarity, rename question fields name/rrtype/rrclass as qname/qtype/qclass +(Global search-and-replace; no functional change to code execution.) + +Revision 1.62 2003/06/04 01:25:33 cheshire + Cannot perform multi-packet known-answer suppression messages +Display time interval between first and subsequent queries + +Revision 1.61 2003/06/03 05:02:16 cheshire + Duplicate registrations not handled as efficiently as they should be + +Revision 1.60 2003/05/31 00:09:49 cheshire + Add ability to discover what services are on a network + +Revision 1.59 2003/05/29 06:11:35 cheshire +: Report if there appear to be too many "Resolve" callbacks + +Revision 1.58 2003/05/29 05:48:06 cheshire +Minor fix for when generating printf warnings: mDNS_snprintf arguments are now 3,4 + +Revision 1.57 2003/05/26 03:21:27 cheshire +Tidy up address structure naming: +mDNSIPAddr => mDNSv4Addr (for consistency with mDNSv6Addr) +mDNSAddr.addr.ipv4 => mDNSAddr.ip.v4 +mDNSAddr.addr.ipv6 => mDNSAddr.ip.v6 + +Revision 1.56 2003/05/26 03:01:27 cheshire + sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead + +Revision 1.55 2003/05/26 00:47:30 cheshire +Comment clarification + +Revision 1.54 2003/05/24 16:39:48 cheshire + SendResponses also needs to handle multihoming better + +Revision 1.53 2003/05/23 02:15:37 cheshire +Fixed misleading use of the term "duplicate suppression" where it should have +said "known answer suppression". (Duplicate answer suppression is something +different, and duplicate question suppression is yet another thing, so the use +of the completely vague term "duplicate suppression" was particularly bad.) + +Revision 1.52 2003/05/22 02:29:22 cheshire + SendQueries needs to handle multihoming better +Complete rewrite of SendQueries. Works much better now :-) + +Revision 1.51 2003/05/21 20:14:55 cheshire +Fix comments and warnings + +Revision 1.50 2003/05/14 07:08:36 cheshire + mDNSResponder should be smarter about reconfigurations +Previously, when there was any network configuration change, mDNSResponder +would tear down the entire list of active interfaces and start again. +That was very disruptive, and caused the entire cache to be flushed, +and caused lots of extra network traffic. Now it only removes interfaces +that have really gone, and only adds new ones that weren't there before. + +Revision 1.49 2003/05/07 01:49:36 cheshire +Remove "const" in ConstructServiceName prototype + +Revision 1.48 2003/05/07 00:18:44 cheshire +Fix typo: "kDNSQClass_Mask" should be "kDNSClass_Mask" + +Revision 1.47 2003/05/06 00:00:46 cheshire + Rationalize naming of domainname manipulation functions + +Revision 1.46 2003/04/30 20:39:09 cheshire +Add comment + +Revision 1.45 2003/04/29 00:40:50 cheshire +Fix compiler warnings + +Revision 1.44 2003/04/26 02:41:56 cheshire + Change timenow from a local variable to a structure member + +Revision 1.43 2003/04/25 01:45:56 cheshire + mDNS_RegisterNoSuchService needs to include a host name + +Revision 1.42 2003/04/15 20:58:31 jgraessl + +Bug #: 3229014 +Added a hash to lookup records in the cache. + +Revision 1.41 2003/04/15 18:09:13 jgraessl + +Bug #: 3228892 +Reviewed by: Stuart Cheshire +Added code to keep track of when the next cache item will expire so we can +call TidyRRCache only when necessary. + +Revision 1.40 2003/03/29 01:55:19 cheshire + mDNSResponder sometimes suffers false self-conflicts when it sees its own packets +Solution: Major cleanup of packet timing and conflict handling rules + +Revision 1.39 2003/03/27 03:30:55 cheshire + Name conflicts not handled properly, resulting in memory corruption, and eventual crash +Problem was that HostNameCallback() was calling mDNS_DeregisterInterface(), which is not safe in a callback +Fixes: +1. Make mDNS_DeregisterInterface() safe to call from a callback +2. Make HostNameCallback() use mDNS_DeadvertiseInterface() instead + (it never really needed to deregister the interface at all) + +Revision 1.38 2003/03/15 04:40:36 cheshire +Change type called "mDNSOpaqueID" to the more descriptive name "mDNSInterfaceID" + +Revision 1.37 2003/03/14 21:34:11 cheshire + Can't setup and print to Lexmark PS printers via Airport Extreme +Increase size of cache rdata from 512 to 768 + +Revision 1.36 2003/03/05 03:38:35 cheshire +Bug #: 3185731 Bogus error message in console: died or deallocated, but no record of client can be found! +Fixed by leaving client in list after conflict, until client explicitly deallocates + +Revision 1.35 2003/02/21 02:47:54 cheshire +Bug #: 3099194 mDNSResponder needs performance improvements +Several places in the code were calling CacheRRActive(), which searched the entire +question list every time, to see if this cache resource record answers any question. +Instead, we now have a field "CRActiveQuestion" in the resource record structure + +Revision 1.34 2003/02/21 01:54:08 cheshire +Bug #: 3099194 mDNSResponder needs performance improvements +Switched to using new "mDNS_Execute" model (see "Implementer Notes.txt") + +Revision 1.33 2003/02/20 06:48:32 cheshire +Bug #: 3169535 Xserve RAID needs to do interface-specific registrations +Reviewed by: Josh Graessley, Bob Bradley + +Revision 1.32 2003/01/31 03:35:59 cheshire +Bug #: 3147097 mDNSResponder sometimes fails to find the correct results +When there were *two* active questions in the list, they were incorrectly +finding *each other* and *both* being marked as duplicates of another question + +Revision 1.31 2003/01/29 02:46:37 cheshire +Fix for IPv6: +A physical interface is identified solely by its InterfaceID (not by IP and type). +On a given InterfaceID, mDNSCore may send both v4 and v6 multicasts. +In cases where the requested outbound protocol (v4 or v6) is not supported on +that InterfaceID, the platform support layer should simply discard that packet. + +Revision 1.30 2003/01/29 01:47:08 cheshire +Rename 'Active' to 'CRActive' or 'InterfaceActive' for improved clarity + +Revision 1.29 2003/01/28 05:23:43 cheshire +Bug #: 3147097 mDNSResponder sometimes fails to find the correct results +Add 'Active' flag for interfaces + +Revision 1.28 2003/01/28 01:35:56 cheshire +Revise comment about ThisQInterval to reflect new semantics + +Revision 1.27 2003/01/13 23:49:42 jgraessl +Merged changes for the following fixes in to top of tree: +3086540 computer name changes not handled properly +3124348 service name changes are not properly handled +3124352 announcements sent in pairs, failing chattiness test + +Revision 1.26 2002/12/23 22:13:28 jgraessl + +Reviewed by: Stuart Cheshire +Initial IPv6 support for mDNSResponder. + +Revision 1.25 2002/09/21 20:44:49 zarzycki +Added APSL info + +Revision 1.24 2002/09/19 23:47:35 cheshire +Added mDNS_RegisterNoSuchService() function for assertion of non-existence +of a particular named service + +Revision 1.23 2002/09/19 21:25:34 cheshire +mDNS_snprintf() doesn't need to be in a separate file + +Revision 1.22 2002/09/19 04:20:43 cheshire +Remove high-ascii characters that confuse some systems + +Revision 1.21 2002/09/17 01:06:35 cheshire +Change mDNS_AdvertiseLocalAddresses to be a parameter to mDNS_Init() + +Revision 1.20 2002/09/16 18:41:41 cheshire +Merge in license terms from Quinn's copy, in preparation for Darwin release + +*/ + +#ifndef __mDNSClientAPI_h +#define __mDNSClientAPI_h + +#include // stdarg.h is required for for va_list support for the mDNS_vsnprintf declaration +#include "mDNSDebug.h" + +#ifdef __cplusplus + extern "C" { +#endif + +// *************************************************************************** +// Function scope indicators + +// If you see "mDNSlocal" before a function name in a C file, it means the function is not callable outside this file +#ifndef mDNSlocal +#define mDNSlocal static +#endif +// If you see "mDNSexport" before a symbol in a C file, it means the symbol is exported for use by clients +// For every "mDNSexport" in a C file, there needs to be a corresponding "extern" declaration in some header file +// (When a C file #includes a header file, the "extern" declarations tell the compiler: +// "This symbol exists -- but not necessarily in this C file.") +#ifndef mDNSexport +#define mDNSexport +#endif + +// *************************************************************************** +// Structure packing macro + +// If we're not using GNUC, it's not fatal. +// Most compilers naturally pack the on-the-wire structures correctly anyway, so a plain "struct" is usually fine. +// In the event that structures are not packed correctly, mDNS_Init() will detect this and report an error, so the +// developer will know what's wrong, and can investigate what needs to be done on that compiler to provide proper packing. +#ifndef packedstruct + #if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 9))) + #define packedstruct struct __attribute__((__packed__)) + #define packedunion union __attribute__((__packed__)) + #else + #define packedstruct struct + #define packedunion union + #endif +#endif + +// *************************************************************************** +#if 0 +#pragma mark - DNS Resource Record class and type constants +#endif + +typedef enum // From RFC 1035 + { + kDNSClass_IN = 1, // Internet + kDNSClass_CS = 2, // CSNET + kDNSClass_CH = 3, // CHAOS + kDNSClass_HS = 4, // Hesiod + kDNSClass_NONE = 254, // Used in DNS UPDATE [RFC 2136] + + kDNSClass_Mask = 0x7FFF,// Multicast DNS uses the bottom 15 bits to identify the record class... + kDNSClass_UniqueRRSet = 0x8000,// ... and the top bit indicates that all other cached records are now invalid + + kDNSQClass_ANY = 255, // Not a DNS class, but a DNS query class, meaning "all classes" + kDNSQClass_UnicastResponse = 0x8000 // Top bit set in a question means "unicast response acceptable" + } DNS_ClassValues; + +typedef enum // From RFC 1035 + { + kDNSType_A = 1, // 1 Address + kDNSType_NS, // 2 Name Server + kDNSType_MD, // 3 Mail Destination + kDNSType_MF, // 4 Mail Forwarder + kDNSType_CNAME, // 5 Canonical Name + kDNSType_SOA, // 6 Start of Authority + kDNSType_MB, // 7 Mailbox + kDNSType_MG, // 8 Mail Group + kDNSType_MR, // 9 Mail Rename + kDNSType_NULL, // 10 NULL RR + kDNSType_WKS, // 11 Well-known-service + kDNSType_PTR, // 12 Domain name pointer + kDNSType_HINFO, // 13 Host information + kDNSType_MINFO, // 14 Mailbox information + kDNSType_MX, // 15 Mail Exchanger + kDNSType_TXT, // 16 Arbitrary text string + + kDNSType_AAAA = 28, // 28 IPv6 address + kDNSType_SRV = 33, // 33 Service record + + kDNSQType_ANY = 255 // Not a DNS type, but a DNS query type, meaning "all types" + } DNS_TypeValues; + +// *************************************************************************** +#if 0 +#pragma mark - Simple types +#endif + +// mDNS defines its own names for these common types to simplify portability across +// multiple platforms that may each have their own (different) names for these types. +typedef int mDNSBool; +typedef signed char mDNSs8; +typedef unsigned char mDNSu8; +typedef signed short mDNSs16; +typedef unsigned short mDNSu16; +#if _LP64 +typedef signed int mDNSs32; +typedef unsigned int mDNSu32; +#else +typedef signed long mDNSs32; +typedef unsigned long mDNSu32; +#endif + +// To enforce useful type checking, we make mDNSInterfaceID be a pointer to a dummy struct +// This way, mDNSInterfaceIDs can be assigned, and compared with each other, but not with other types +// Declaring the type to be the typical generic "void *" would lack this type checking +typedef struct mDNSInterfaceID_dummystruct { void *dummy; } *mDNSInterfaceID; + +// These types are for opaque two- and four-byte identifiers. +// The "NotAnInteger" fields of the unions allow the value to be conveniently passed around in a +// register for the sake of efficiency, and compared for equality or inequality, but don't forget -- +// just because it is in a register doesn't mean it is an integer. Operations like greater than, +// less than, add, multiply, increment, decrement, etc., are undefined for opaque identifiers, +// and if you make the mistake of trying to do those using the NotAnInteger field, then you'll +// find you get code that doesn't work consistently on big-endian and little-endian machines. +typedef packedunion { mDNSu8 b[2]; mDNSu16 NotAnInteger; } mDNSOpaque16; +typedef packedunion { mDNSu8 b[4]; mDNSu32 NotAnInteger; } mDNSOpaque32; +typedef packedunion { mDNSu8 b[16]; mDNSu16 w[8]; mDNSu32 l[4]; } mDNSOpaque128; + +typedef mDNSOpaque16 mDNSIPPort; // An IP port is a two-byte opaque identifier (not an integer) +typedef mDNSOpaque32 mDNSv4Addr; // An IP address is a four-byte opaque identifier (not an integer) +typedef mDNSOpaque128 mDNSv6Addr; // An IPv6 address is a 16-byte opaque identifier (not an integer) + +enum + { + mDNSAddrType_None = 0, + mDNSAddrType_IPv4 = 4, + mDNSAddrType_IPv6 = 6, + mDNSAddrType_Unknown = ~0 // Special marker value used in known answer list recording + }; + +typedef struct + { + mDNSs32 type; + union { mDNSv6Addr v6; mDNSv4Addr v4; } ip; + } mDNSAddr; + +enum { mDNSfalse = 0, mDNStrue = 1 }; + +#define mDNSNULL 0L + +enum + { + mStatus_Waiting = 1, + mStatus_NoError = 0, + + // mDNS return values are in the range FFFE FF00 (-65792) to FFFE FFFF (-65537) + // The top end of the range (FFFE FFFF) is used for error codes; + // the bottom end of the range (FFFE FF00) is used for non-error values; + + // Error codes: + mStatus_UnknownErr = -65537, // 0xFFFE FFFF + mStatus_NoSuchNameErr = -65538, + mStatus_NoMemoryErr = -65539, + mStatus_BadParamErr = -65540, + mStatus_BadReferenceErr = -65541, + mStatus_BadStateErr = -65542, + mStatus_BadFlagsErr = -65543, + mStatus_UnsupportedErr = -65544, + mStatus_NotInitializedErr = -65545, + mStatus_NoCache = -65546, + mStatus_AlreadyRegistered = -65547, + mStatus_NameConflict = -65548, + mStatus_Invalid = -65549, + // = -65550, + mStatus_Incompatible = -65551, + mStatus_BadInterfaceErr = -65552, + + // -65553 - -65789 currently unused + + // Non-error values: + mStatus_GrowCache = -65790, + mStatus_ConfigChanged = -65791, + mStatus_MemFree = -65792 // 0xFFFE FF00 + }; + +typedef mDNSs32 mStatus; + +// RFC 1034/1035 specify that a domain label consists of a length byte plus up to 63 characters +#define MAX_DOMAIN_LABEL 63 +typedef struct { mDNSu8 c[ 64]; } domainlabel; // One label: length byte and up to 63 characters + +// RFC 1034/1035 specify that a domain name, including length bytes, data bytes, and terminating zero, may be up to 255 bytes long +#define MAX_DOMAIN_NAME 255 +typedef struct { mDNSu8 c[256]; } domainname; // Up to 255 bytes of length-prefixed domainlabels + +typedef struct { mDNSu8 c[256]; } UTF8str255; // Null-terminated C string + +// The longest legal textual form of a DNS name is 1005 bytes, including the C-string terminating NULL at the end. +// Explanation: +// When a native domainname object is converted to printable textual form using ConvertDomainNameToCString(), +// non-printing characters are represented in the conventional DNS way, as '\ddd', where ddd is a three-digit decimal number. +// The longest legal domain name is 255 bytes, in the form of four labels as shown below: +// Length byte, 63 data bytes, length byte, 63 data bytes, length byte, 63 data bytes, length byte, 61 data bytes, zero byte. +// Each label is encoded textually as characters followed by a trailing dot. +// If every character has to be represented as a four-byte escape sequence, then this makes the maximum textual form four labels +// plus the C-string terminating NULL as shown below: +// 63*4+1 + 63*4+1 + 63*4+1 + 61*4+1 + 1 = 1005. +// Note that MAX_ESCAPED_DOMAIN_LABEL is not normally used: If you're only decoding a single label, escaping is usually not required. +// It is for domain names, where dots are used as label separators, that proper escaping is vital. +#define MAX_ESCAPED_DOMAIN_LABEL 254 +#define MAX_ESCAPED_DOMAIN_NAME 1005 + +// *************************************************************************** +#if 0 +#pragma mark - Resource Record structures +#endif + +// Authoritative Resource Records: +// There are four basic types: Shared, Advisory, Unique, Known Unique + +// * Shared Resource Records do not have to be unique +// -- Shared Resource Records are used for DNS-SD service PTRs +// -- It is okay for several hosts to have RRs with the same name but different RDATA +// -- We use a random delay on responses to reduce collisions when all the hosts respond to the same query +// -- These RRs typically have moderately high TTLs (e.g. one hour) +// -- These records are announced on startup and topology changes for the benefit of passive listeners +// -- These records send a goodbye packet when deregistering +// +// * Advisory Resource Records are like Shared Resource Records, except they don't send a goodbye packet +// +// * Unique Resource Records should be unique among hosts within any given mDNS scope +// -- The majority of Resource Records are of this type +// -- If two entities on the network have RRs with the same name but different RDATA, this is a conflict +// -- Responses may be sent immediately, because only one host should be responding to any particular query +// -- These RRs typically have low TTLs (e.g. ten seconds) +// -- On startup and after topology changes, a host issues queries to verify uniqueness + +// * Known Unique Resource Records are treated like Unique Resource Records, except that mDNS does +// not have to verify their uniqueness because this is already known by other means (e.g. the RR name +// is derived from the host's IP or Ethernet address, which is already known to be a unique identifier). + +// Summary of properties of different record types: +// Probe? Does this record type send probes before announcing? +// Conflict? Does this record type react if we observe an apparent conflict? +// Goodbye? Does this record type send a goodbye packet on departure? +// +// Probe? Conflict? Goodbye? Notes +// Unregistered Should not appear in any list (sanity check value) +// Shared No No Yes e.g. Service PTR record +// Deregistering No No Yes Shared record about to announce its departure and leave the list +// Advisory No No No +// Unique Yes Yes No Record intended to be unique -- will probe to verify +// Verified Yes Yes No Record has completed probing, and is verified unique +// KnownUnique No Yes No Record is assumed by other means to be unique + +// Valid lifecycle of a record: +// Unregistered -> Shared -> Deregistering -(goodbye)-> Unregistered +// Unregistered -> Advisory -> Unregistered +// Unregistered -> Unique -(probe)-> Verified -> Unregistered +// Unregistered -> KnownUnique -> Unregistered + +// Each Authoritative kDNSRecordType has only one bit set. This makes it easy to quickly see if a record +// is one of a particular set of types simply by performing the appropriate bitwise masking operation. + +// Cache Resource Records (received from the network): +// There are four basic types: Answer, Unique Answer, Additional, Unique Additional +// Bit 7 (the top bit) of kDNSRecordType is always set for Cache Resource Records; always clear for Authoritative Resource Records +// Bit 6 (value 0x40) is set for answer records; clear for additional records +// Bit 5 (value 0x20) is set for records received with the kDNSClass_UniqueRRSet + +enum + { + kDNSRecordTypeUnregistered = 0x00, // Not currently in any list + kDNSRecordTypeDeregistering = 0x01, // Shared record about to announce its departure and leave the list + + kDNSRecordTypeUnique = 0x02, // Will become a kDNSRecordTypeVerified when probing is complete + + kDNSRecordTypeAdvisory = 0x04, // Like Shared, but no goodbye packet + kDNSRecordTypeShared = 0x08, // Shared means record name does not have to be unique -- use random delay on responses + kDNSRecordTypeVerified = 0x10, // Unique means mDNS should check that name is unique (and then send immediate responses) + kDNSRecordTypeKnownUnique = 0x20, // Known Unique means mDNS can assume name is unique without checking + + kDNSRecordTypeUniqueMask = (kDNSRecordTypeUnique | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique), + kDNSRecordTypeActiveMask = (kDNSRecordTypeAdvisory | kDNSRecordTypeShared | kDNSRecordTypeVerified | kDNSRecordTypeKnownUnique), + + kDNSRecordTypePacketAdd = 0x80, // Received in the Additional Section of a DNS Response + kDNSRecordTypePacketAddUnique = 0xA0, // Received in the Additional Section of a DNS Response with kDNSClass_UniqueRRSet set + kDNSRecordTypePacketAns = 0xC0, // Received in the Answer Section of a DNS Response + kDNSRecordTypePacketAnsUnique = 0xE0, // Received in the Answer Section of a DNS Response with kDNSClass_UniqueRRSet set + + kDNSRecordTypePacketAnsMask = 0x40, // True for PacketAns and PacketAnsUnique + kDNSRecordTypePacketUniqueMask = 0x20 // True for PacketAddUnique and PacketAnsUnique + }; + +typedef packedstruct { mDNSu16 priority; mDNSu16 weight; mDNSIPPort port; domainname target; } rdataSRV; +typedef packedstruct { mDNSu16 preference; domainname exchange; } rdataMX; + +// StandardAuthRDSize is 264 (256+8), which is large enough to hold a maximum-sized SRV record +// MaximumRDSize is 8K the absolute maximum we support (at least for now) +#define StandardAuthRDSize 264 +#define MaximumRDSize 8192 + +// InlineCacheRDSize is 64 +// Records received from the network with rdata this size or less have their rdata stored right in the CacheRecord object +// Records received from the network with rdata larger than this have additional storage allocated for the rdata +// A quick unscientific sample from a busy network at Apple with lots of machines revealed this: +// 1461 records in cache +// 292 were one-byte TXT records +// 136 were four-byte A records +// 184 were sixteen-byte AAAA records +// 780 were various PTR, TXT and SRV records from 12-64 bytes +// Only 69 records had rdata bigger than 64 bytes +#define InlineCacheRDSize 64 + +typedef union + { + mDNSu8 data[StandardAuthRDSize]; + mDNSv4Addr ip; // For 'A' record + mDNSv6Addr ipv6; // For 'AAAA' record + domainname name; // For PTR and CNAME records + UTF8str255 txt; // For TXT record + rdataSRV srv; // For SRV record + rdataMX mx; // For MX record + } RDataBody; + +typedef struct + { + mDNSu16 MaxRDLength; // Amount of storage allocated for rdata (usually sizeof(RDataBody)) + RDataBody u; + } RData; +#define sizeofRDataHeader (sizeof(RData) - sizeof(RDataBody)) + +typedef struct AuthRecord_struct AuthRecord; +typedef struct CacheRecord_struct CacheRecord; +typedef struct ResourceRecord_struct ResourceRecord; +typedef struct DNSQuestion_struct DNSQuestion; +typedef struct mDNS_struct mDNS; +typedef struct mDNS_PlatformSupport_struct mDNS_PlatformSupport; + +// Note: Within an mDNSRecordCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute() +typedef void mDNSRecordCallback(mDNS *const m, AuthRecord *const rr, mStatus result); + +// Note: +// Restrictions: An mDNSRecordUpdateCallback may not make any mDNS API calls. +// The intent of this callback is to allow the client to free memory, if necessary. +// The internal data structures of the mDNS code may not be in a state where mDNS API calls may be made safely. +typedef void mDNSRecordUpdateCallback(mDNS *const m, AuthRecord *const rr, RData *OldRData); + +struct ResourceRecord_struct + { + mDNSu8 RecordType; // See enum above + mDNSInterfaceID InterfaceID; // Set if this RR is specific to one interface + // For records received off the wire, InterfaceID is *always* set to the receiving interface + // For our authoritative records, InterfaceID is usually zero, except for those few records + // that are interface-specific (e.g. address records, especially linklocal addresses) + domainname name; + mDNSu16 rrtype; + mDNSu16 rrclass; + mDNSu32 rroriginalttl; // In seconds + mDNSu16 rdlength; // Size of the raw rdata, in bytes + mDNSu16 rdestimate; // Upper bound on size of rdata after name compression + mDNSu32 namehash; // Name-based (i.e. case insensitive) hash of name + mDNSu32 rdatahash; // 32-bit hash of the raw rdata + mDNSu32 rdnamehash; // Set if this rdata contains a domain name (e.g. PTR, SRV, CNAME etc.) + RData *rdata; // Pointer to storage for this rdata + }; + +struct AuthRecord_struct + { + // For examples of how to set up this structure for use in mDNS_Register(), + // see mDNS_AdvertiseInterface() or mDNS_RegisterService(). + // Basically, resrec and persistent metadata need to be set up before calling mDNS_Register(). + // mDNS_SetupResourceRecord() is avaliable as a helper routine to set up most fields to sensible default values for you + + AuthRecord *next; // Next in list; first element of structure for efficiency reasons + ResourceRecord resrec; + + // Persistent metadata for Authoritative Records + AuthRecord *Additional1; // Recommended additional record to include in response + AuthRecord *Additional2; // Another additional + AuthRecord *DependentOn; // This record depends on another for its uniqueness checking + AuthRecord *RRSet; // This unique record is part of an RRSet + mDNSRecordCallback *RecordCallback; // Callback function to call for state changes + void *RecordContext; // Context parameter for the callback function + mDNSu8 HostTarget; // Set if the target of this record (PTR, CNAME, SRV, etc.) is our host name + + // Transient state for Authoritative Records + mDNSu8 Acknowledged; // Set if we've given the success callback to the client + mDNSu8 ProbeCount; // Number of probes remaining before this record is valid (kDNSRecordTypeUnique) + mDNSu8 AnnounceCount; // Number of announcements remaining (kDNSRecordTypeShared) + mDNSu8 IncludeInProbe; // Set if this RR is being put into a probe right now + mDNSInterfaceID ImmedAnswer; // Someone on this interface issued a query we need to answer (all-ones for all interfaces) + mDNSInterfaceID ImmedAdditional; // Hint that we might want to also send this record, just to be helpful + mDNSInterfaceID SendRNow; // The interface this query is being sent on right now + mDNSv4Addr v4Requester; // Recent v4 query for this record, or all-ones if more than one recent query + mDNSv6Addr v6Requester; // Recent v6 query for this record, or all-ones if more than one recent query + AuthRecord *NextResponse; // Link to the next element in the chain of responses to generate + const mDNSu8 *NR_AnswerTo; // Set if this record was selected by virtue of being a direct answer to a question + AuthRecord *NR_AdditionalTo; // Set if this record was selected by virtue of being additional to another + mDNSs32 ThisAPInterval; // In platform time units: Current interval for announce/probe + mDNSs32 AnnounceUntil; // In platform time units: Creation time + TTL + mDNSs32 LastAPTime; // In platform time units: Last time we sent announcement/probe + mDNSs32 LastMCTime; // Last time we multicast this record (used to guard against packet-storm attacks) + mDNSInterfaceID LastMCInterface; // Interface this record was multicast on at the time LastMCTime was recorded + RData *NewRData; // Set if we are updating this record with new rdata + mDNSu16 newrdlength; // ... and the length of the new RData + mDNSRecordUpdateCallback *UpdateCallback; + mDNSu32 UpdateCredits; // Token-bucket rate limiting of excessive updates + mDNSs32 NextUpdateCredit; // Time next token is added to bucket + mDNSs32 UpdateBlocked; // Set if update delaying is in effect + + RData rdatastorage; // Normally the storage is right here, except for oversized records + // rdatastorage MUST be the last thing in the structure -- when using oversized AuthRecords, extra bytes + // are appended after the end of the AuthRecord, logically augmenting the size of the rdatastorage + // DO NOT ADD ANY MORE FIELDS HERE + }; + +struct CacheRecord_struct + { + CacheRecord *next; // Next in list; first element of structure for efficiency reasons + ResourceRecord resrec; + + // Transient state for Cache Records + CacheRecord *NextInKAList; // Link to the next element in the chain of known answers to send + mDNSs32 TimeRcvd; // In platform time units + mDNSs32 NextRequiredQuery; // In platform time units + mDNSs32 LastUsed; // In platform time units + mDNSu32 UseCount; // Number of times this RR has been used to answer a question + DNSQuestion *CRActiveQuestion; // Points to an active question referencing this answer + mDNSu32 UnansweredQueries; // Number of times we've issued a query for this record without getting an answer + mDNSs32 LastUnansweredTime; // In platform time units; last time we incremented UnansweredQueries + mDNSu32 MPUnansweredQ; // Multi-packet query handling: Number of times we've seen a query for this record + mDNSs32 MPLastUnansweredQT; // Multi-packet query handling: Last time we incremented MPUnansweredQ + mDNSu32 MPUnansweredKA; // Multi-packet query handling: Number of times we've seen this record in a KA list + mDNSBool MPExpectingKA; // Multi-packet query handling: Set when we increment MPUnansweredQ; allows one KA + CacheRecord *NextInCFList; // Set if this is in the list of records we just received with the cache flush bit set + + struct { mDNSu16 MaxRDLength; mDNSu8 data[InlineCacheRDSize]; } rdatastorage; // Storage for small records is right here + }; + +typedef struct + { + CacheRecord r; + mDNSu8 _extradata[MaximumRDSize-InlineCacheRDSize]; // Glue on the necessary number of extra bytes + } LargeCacheRecord; + +typedef struct NetworkInterfaceInfo_struct NetworkInterfaceInfo; + +struct NetworkInterfaceInfo_struct + { + // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them. + NetworkInterfaceInfo *next; + + mDNSBool InterfaceActive; // InterfaceActive is set if interface is sending & receiving packets + // InterfaceActive is clear if interface is here to represent an address with A + // and/or AAAA records, but there is already an earlier representative for this + // physical interface which will be used for the actual sending & receiving + // packets (this status may change as interfaces are added and removed) + mDNSBool IPv4Available; // If InterfaceActive, set if v4 available on this InterfaceID + mDNSBool IPv6Available; // If InterfaceActive, set if v6 available on this InterfaceID + + // Standard AuthRecords that every Responder host should have (one per active IP address) + AuthRecord RR_A; // 'A' or 'AAAA' (address) record for our ".local" name + AuthRecord RR_PTR; // PTR (reverse lookup) record + AuthRecord RR_HINFO; + + // Client API fields: The client must set up these fields *before* calling mDNS_RegisterInterface() + mDNSInterfaceID InterfaceID; + mDNSAddr ip; + mDNSBool Advertise; // Set Advertise to false if you are only searching on this interface + mDNSBool TxAndRx; // Set to false if not sending and receiving packets on this interface + }; + +typedef struct ExtraResourceRecord_struct ExtraResourceRecord; +struct ExtraResourceRecord_struct + { + ExtraResourceRecord *next; + AuthRecord r; + // Note: Add any additional fields *before* the AuthRecord in this structure, not at the end. + // In some cases clients can allocate larger chunks of memory and set r->rdata->MaxRDLength to indicate + // that this extra memory is available, which would result in any fields after the AuthRecord getting smashed + }; + +// Note: Within an mDNSServiceCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute() +typedef struct ServiceRecordSet_struct ServiceRecordSet; +typedef void mDNSServiceCallback(mDNS *const m, ServiceRecordSet *const sr, mStatus result); +struct ServiceRecordSet_struct + { + // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them. + // No fields need to be set up by the client prior to calling mDNS_RegisterService(); + // all required data is passed as parameters to that function. + mDNSServiceCallback *ServiceCallback; + void *ServiceContext; + ExtraResourceRecord *Extras; // Optional list of extra AuthRecords attached to this service registration + mDNSu32 NumSubTypes; + AuthRecord *SubTypes; + mDNSBool Conflict; // Set if this record set was forcibly deregistered because of a conflict + domainname Host; // Set if this service record does not use the standard target host name + AuthRecord RR_ADV; // e.g. _services._dns-sd._udp.local. PTR _printer._tcp.local. + AuthRecord RR_PTR; // e.g. _printer._tcp.local. PTR Name._printer._tcp.local. + AuthRecord RR_SRV; // e.g. Name._printer._tcp.local. SRV 0 0 port target + AuthRecord RR_TXT; // e.g. Name._printer._tcp.local. TXT PrintQueueName + // Don't add any fields after AuthRecord RR_TXT. + // This is where the implicit extra space goes if we allocate a ServiceRecordSet containing an oversized RR_TXT record + }; + +// *************************************************************************** +#if 0 +#pragma mark - Question structures +#endif + +// We record the last eight instances of each duplicate query +// This gives us v4/v6 on each of Ethernet/AirPort and Firewire, and two free slots "for future expansion" +// If the host has more active interfaces that this it is not fatal -- duplicate question suppression will degrade gracefully. +// Since we will still remember the last eight, the busiest interfaces will still get the effective duplicate question suppression. +#define DupSuppressInfoSize 8 + +typedef struct + { + mDNSs32 Time; + mDNSInterfaceID InterfaceID; + mDNSs32 Type; // v4 or v6? + } DupSuppressInfo; + +// Note: Within an mDNSQuestionCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute() +typedef void mDNSQuestionCallback(mDNS *const m, DNSQuestion *question, const ResourceRecord *const answer, mDNSBool AddRecord); +struct DNSQuestion_struct + { + // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them. + DNSQuestion *next; + mDNSu32 qnamehash; + mDNSs32 LastQTime; // Last scheduled transmission of this Q on *all* applicable interfaces + mDNSs32 ThisQInterval; // LastQTime + ThisQInterval is the next scheduled transmission of this Q + // ThisQInterval > 0 for an active question; + // ThisQInterval = 0 for a suspended question that's still in the list + // ThisQInterval = -1 for a cancelled question that's been removed from the list + mDNSu32 RecentAnswers; // Number of answers since the last time we sent this query + mDNSu32 CurrentAnswers; // Number of records currently in the cache that answer this question + mDNSu32 LargeAnswers; // Number of answers with rdata > 1024 bytes + mDNSu32 UniqueAnswers; // Number of answers received with kDNSClass_UniqueRRSet bit set + DNSQuestion *DuplicateOf; + DNSQuestion *NextInDQList; + DupSuppressInfo DupSuppress[DupSuppressInfoSize]; + mDNSInterfaceID SendQNow; // The interface this query is being sent on right now + mDNSBool SendOnAll; // Set if we're sending this question on all active interfaces + mDNSs32 LastQTxTime; // Last time this Q was sent on one (but not necessarily all) interfaces + + // Client API fields: The client must set up these fields *before* calling mDNS_StartQuery() + mDNSInterfaceID InterfaceID; // Non-zero if you want to issue link-local queries only on a single specific IP interface + domainname qname; + mDNSu16 qtype; + mDNSu16 qclass; + mDNSQuestionCallback *QuestionCallback; + void *QuestionContext; + }; + +typedef struct + { + // Client API fields: The client must set up name and InterfaceID *before* calling mDNS_StartResolveService() + // When the callback is invoked, ip, port, TXTlen and TXTinfo will have been filled in with the results learned from the network. + domainname name; + mDNSInterfaceID InterfaceID; // ID of the interface the response was received on + mDNSAddr ip; // Remote (destination) IP address where this service can be accessed + mDNSIPPort port; // Port where this service can be accessed + mDNSu16 TXTlen; + mDNSu8 TXTinfo[2048]; // Additional demultiplexing information (e.g. LPR queue name) + } ServiceInfo; + +// Note: Within an mDNSServiceInfoQueryCallback mDNS all API calls are legal except mDNS_Init(), mDNS_Close(), mDNS_Execute() +typedef struct ServiceInfoQuery_struct ServiceInfoQuery; +typedef void mDNSServiceInfoQueryCallback(mDNS *const m, ServiceInfoQuery *query); +struct ServiceInfoQuery_struct + { + // Internal state fields. These are used internally by mDNSCore; the client layer needn't be concerned with them. + // No fields need to be set up by the client prior to calling mDNS_StartResolveService(); + // all required data is passed as parameters to that function. + // The ServiceInfoQuery structure memory is working storage for mDNSCore to discover the requested information + // and place it in the ServiceInfo structure. After the client has called mDNS_StopResolveService(), it may + // dispose of the ServiceInfoQuery structure while retaining the results in the ServiceInfo structure. + DNSQuestion qSRV; + DNSQuestion qTXT; + DNSQuestion qAv4; + DNSQuestion qAv6; + mDNSu8 GotSRV; + mDNSu8 GotTXT; + mDNSu8 GotADD; + mDNSu32 Answers; + ServiceInfo *info; + mDNSServiceInfoQueryCallback *ServiceInfoQueryCallback; + void *ServiceInfoQueryContext; + }; + +// *************************************************************************** +#if 0 +#pragma mark - Main mDNS object, used to hold all the mDNS state +#endif + +typedef void mDNSCallback(mDNS *const m, mStatus result); + +#define CACHE_HASH_SLOTS 499 + +enum + { + mDNS_KnownBug_PhantomInterfaces = 1 + }; + +struct mDNS_struct + { + // Internal state fields. These hold the main internal state of mDNSCore; + // the client layer needn't be concerned with them. + // No fields need to be set up by the client prior to calling mDNS_Init(); + // all required data is passed as parameters to that function. + + mDNS_PlatformSupport *p; // Pointer to platform-specific data of indeterminite size + mDNSu32 KnownBugs; + mDNSBool AdvertiseLocalAddresses; + mStatus mDNSPlatformStatus; + mDNSCallback *MainCallback; + void *MainContext; + + // For debugging: To catch and report locking failures + mDNSu32 mDNS_busy; // Incremented between mDNS_Lock/mDNS_Unlock section + mDNSu32 mDNS_reentrancy; // Incremented when calling a client callback + mDNSu8 mDNS_shutdown; // Set when we're shutting down, allows us to skip some unnecessary steps + mDNSu8 lock_rrcache; // For debugging: Set at times when these lists may not be modified + mDNSu8 lock_Questions; + mDNSu8 lock_Records; + char MsgBuffer[80]; // Temp storage used while building error log messages + + // Task Scheduling variables + mDNSs32 timenow; // The time that this particular activation of the mDNS code started + mDNSs32 timenow_last; // The time the last time we ran + mDNSs32 timenow_adjust; // Correction applied if we ever discover time went backwards + mDNSs32 NextScheduledEvent; // Derived from values below + mDNSs32 SuppressSending; // Don't send *any* packets during this time + mDNSs32 NextCacheCheck; // Next time to refresh cache record before it expires + mDNSs32 NextScheduledQuery; // Next time to send query in its exponential backoff sequence + mDNSs32 NextScheduledProbe; // Next time to probe for new authoritative record + mDNSs32 NextScheduledResponse; // Next time to send authoritative record(s) in responses + mDNSs32 ExpectUnicastResponse; // Set when we send a query with the kDNSQClass_UnicastResponse bit set + mDNSs32 RandomQueryDelay; // For de-synchronization of query packets on the wire + mDNSBool SendDeregistrations; // Set if we need to send deregistrations (immediately) + mDNSBool SendImmediateAnswers; // Set if we need to send answers (immediately -- or as soon as SuppressSending clears) + mDNSBool SleepState; // Set if we're sleeping (send no more packets) + + // These fields only required for mDNS Searcher... + DNSQuestion *Questions; // List of all registered questions, active and inactive + DNSQuestion *NewQuestions; // Fresh questions not yet answered from cache + DNSQuestion *CurrentQuestion; // Next question about to be examined in AnswerLocalQuestions() + DNSQuestion *LocalOnlyQuestions; // Questions with InterfaceID set to ~0 ("local only") + DNSQuestion *NewLocalOnlyQuestions; // Fresh local-only questions not yet answered + mDNSu32 rrcache_size; // Total number of available cache entries + mDNSu32 rrcache_totalused; // Number of cache entries currently occupied + mDNSu32 rrcache_active; // Number of cache entries currently occupied by records that answer active questions + mDNSu32 rrcache_report; + CacheRecord *rrcache_free; + CacheRecord *rrcache_hash[CACHE_HASH_SLOTS]; + CacheRecord **rrcache_tail[CACHE_HASH_SLOTS]; + mDNSu32 rrcache_used[CACHE_HASH_SLOTS]; + + // Fields below only required for mDNS Responder... + domainlabel nicelabel; // Rich text label encoded using canonically precomposed UTF-8 + domainlabel hostlabel; // Conforms to RFC 1034 "letter-digit-hyphen" ARPANET host name rules + domainname hostname; // Host Name, e.g. "Foo.local." + UTF8str255 HIHardware; + UTF8str255 HISoftware; + AuthRecord *ResourceRecords; + AuthRecord *DuplicateRecords; // Records currently 'on hold' because they are duplicates of existing records + AuthRecord *LocalOnlyRecords; // Local records registered with InterfaceID set to ~0 ("local only") + AuthRecord *NewLocalOnlyRecords; // Fresh local-only records not yet delivered to local-only questions + mDNSBool DiscardLocalOnlyRecords;// Set when we have "remove" events we need to deliver to local-only questions + AuthRecord *CurrentRecord; // Next AuthRecord about to be examined + NetworkInterfaceInfo *HostInterfaces; + mDNSs32 ProbeFailTime; + mDNSs32 NumFailedProbes; + mDNSs32 SuppressProbes; + }; + +// *************************************************************************** +#if 0 +#pragma mark - Useful Static Constants +#endif + +extern const mDNSIPPort zeroIPPort; +extern const mDNSv4Addr zeroIPAddr; +extern const mDNSv6Addr zerov6Addr; +extern const mDNSv4Addr onesIPv4Addr; +extern const mDNSv6Addr onesIPv6Addr; +extern const mDNSInterfaceID mDNSInterface_Any; + +extern const mDNSIPPort UnicastDNSPort; +extern const mDNSIPPort MulticastDNSPort; +extern const mDNSv4Addr AllDNSAdminGroup; +extern const mDNSv4Addr AllDNSLinkGroup; +extern const mDNSv6Addr AllDNSLinkGroupv6; +extern const mDNSAddr AllDNSLinkGroup_v4; +extern const mDNSAddr AllDNSLinkGroup_v6; + +// *************************************************************************** +#if 0 +#pragma mark - Main Client Functions +#endif + +// Every client should call mDNS_Init, passing in storage for the mDNS object, mDNS_PlatformSupport object, and rrcache. +// The rrcachesize parameter is the size of (i.e. number of entries in) the rrcache array passed in. +// Most clients use mDNS_Init_AdvertiseLocalAddresses. This causes mDNSCore to automatically +// create the correct address records for all the hosts interfaces. If you plan to advertise +// services being offered by the local machine, this is almost always what you want. +// There are two cases where you might use mDNS_Init_DontAdvertiseLocalAddresses: +// 1. A client-only device, that browses for services but doesn't advertise any of its own. +// 2. A proxy-registration service, that advertises services being offered by other machines, and takes +// the appropriate steps to manually create the correct address records for those other machines. +// In principle, a proxy-like registration service could manually create address records for its own machine too, +// but this would be pointless extra effort when using mDNS_Init_AdvertiseLocalAddresses does that for you. +// +// When mDNS has finished setting up the client's callback is called +// A client can also spin and poll the mDNSPlatformStatus field to see when it changes from mStatus_Waiting to mStatus_NoError +// +// Call mDNS_Close to tidy up before exiting +// +// Call mDNS_Register with a completed AuthRecord object to register a resource record +// If the resource record type is kDNSRecordTypeUnique (or kDNSknownunique) then if a conflicting resource record is discovered, +// the resource record's mDNSRecordCallback will be called with error code mStatus_NameConflict. The callback should deregister +// the record, and may then try registering the record again after picking a new name (e.g. by automatically appending a number). +// +// Call mDNS_StartQuery to initiate a query. mDNS will proceed to issue Multicast DNS query packets, and any time a response +// is received containing a record which matches the question, the DNSQuestion's mDNSAnswerCallback function will be called +// Call mDNS_StopQuery when no more answers are required +// +// Care should be taken on multi-threaded or interrupt-driven environments. +// The main mDNS routines call mDNSPlatformLock() on entry and mDNSPlatformUnlock() on exit; +// each platform layer needs to implement these appropriately for its respective platform. +// For example, if the support code on a particular platform implements timer callbacks at interrupt time, then +// mDNSPlatformLock/Unlock need to disable interrupts or do similar concurrency control to ensure that the mDNS +// code is not entered by an interrupt-time timer callback while in the middle of processing a client call. + +extern mStatus mDNS_Init (mDNS *const m, mDNS_PlatformSupport *const p, + CacheRecord *rrcachestorage, mDNSu32 rrcachesize, + mDNSBool AdvertiseLocalAddresses, + mDNSCallback *Callback, void *Context); +// See notes above on use of NoCache/ZeroCacheSize +#define mDNS_Init_NoCache mDNSNULL +#define mDNS_Init_ZeroCacheSize 0 +// See notes above on use of Advertise/DontAdvertiseLocalAddresses +#define mDNS_Init_AdvertiseLocalAddresses mDNStrue +#define mDNS_Init_DontAdvertiseLocalAddresses mDNSfalse +#define mDNS_Init_NoInitCallback mDNSNULL +#define mDNS_Init_NoInitCallbackContext mDNSNULL + +extern void mDNS_GrowCache (mDNS *const m, CacheRecord *storage, mDNSu32 numrecords); +extern void mDNS_Close (mDNS *const m); +extern mDNSs32 mDNS_Execute (mDNS *const m); + +extern mStatus mDNS_Register (mDNS *const m, AuthRecord *const rr); +extern mStatus mDNS_Update (mDNS *const m, AuthRecord *const rr, mDNSu32 newttl, + const mDNSu16 newrdlength, + RData *const newrdata, mDNSRecordUpdateCallback *Callback); +extern mStatus mDNS_Deregister(mDNS *const m, AuthRecord *const rr); + +extern mStatus mDNS_StartQuery(mDNS *const m, DNSQuestion *const question); +extern mStatus mDNS_StopQuery (mDNS *const m, DNSQuestion *const question); +extern mStatus mDNS_Reconfirm (mDNS *const m, CacheRecord *const cacherr); +extern mStatus mDNS_ReconfirmByValue(mDNS *const m, ResourceRecord *const rr); + +// *************************************************************************** +#if 0 +#pragma mark - Platform support functions that are accessible to the client layer too +#endif + +extern mDNSs32 mDNSPlatformOneSecond; +extern mDNSs32 mDNSPlatformTimeNow(void); + +// *************************************************************************** +#if 0 +#pragma mark - General utility and helper functions +#endif + +// mDNS_RegisterService is a single call to register the set of resource records associated with a given named service. +// +// mDNS_StartResolveService is single call which is equivalent to multiple calls to mDNS_StartQuery, +// to find the IP address, port number, and demultiplexing information for a given named service. +// As with mDNS_StartQuery, it executes asynchronously, and calls the ServiceInfoQueryCallback when the answer is +// found. After the service is resolved, the client should call mDNS_StopResolveService to complete the transaction. +// The client can also call mDNS_StopResolveService at any time to abort the transaction. +// +// mDNS_GetBrowseDomains is a special case of the mDNS_StartQuery call, where the resulting answers +// are a list of PTR records indicating (in the rdata) domains that are recommended for browsing. +// After getting the list of domains to browse, call mDNS_StopQuery to end the search. +// mDNS_GetDefaultBrowseDomain returns the name of the domain that should be highlighted by default. +// +// mDNS_GetRegistrationDomains and mDNS_GetDefaultRegistrationDomain are the equivalent calls to get the list +// of one or more domains that should be offered to the user as choices for where they may register their service, +// and the default domain in which to register in the case where the user has made no selection. + +extern void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mDNSInterfaceID InterfaceID, + mDNSu16 rrtype, mDNSu32 ttl, mDNSu8 RecordType, mDNSRecordCallback Callback, void *Context); + +extern mStatus mDNS_RegisterService (mDNS *const m, ServiceRecordSet *sr, + const domainlabel *const name, const domainname *const type, const domainname *const domain, + const domainname *const host, mDNSIPPort port, const mDNSu8 txtinfo[], mDNSu16 txtlen, + AuthRecord *SubTypes, mDNSu32 NumSubTypes, + const mDNSInterfaceID InterfaceID, mDNSServiceCallback Callback, void *Context); +extern mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra, RData *rdata, mDNSu32 ttl); +extern mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet *sr, ExtraResourceRecord *extra); +extern mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordSet *const sr, const domainlabel *newname); +extern mStatus mDNS_DeregisterService(mDNS *const m, ServiceRecordSet *sr); + +extern mStatus mDNS_RegisterNoSuchService(mDNS *const m, AuthRecord *const rr, + const domainlabel *const name, const domainname *const type, const domainname *const domain, + const domainname *const host, + const mDNSInterfaceID InterfaceID, mDNSRecordCallback Callback, void *Context); +#define mDNS_DeregisterNoSuchService mDNS_Deregister + +extern mStatus mDNS_StartBrowse(mDNS *const m, DNSQuestion *const question, + const domainname *const srv, const domainname *const domain, + const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context); +#define mDNS_StopBrowse mDNS_StopQuery + +extern mStatus mDNS_StartResolveService(mDNS *const m, ServiceInfoQuery *query, ServiceInfo *info, mDNSServiceInfoQueryCallback *Callback, void *Context); +extern void mDNS_StopResolveService (mDNS *const m, ServiceInfoQuery *query); + +typedef enum + { + mDNS_DomainTypeBrowse = 0, + mDNS_DomainTypeBrowseDefault = 1, + mDNS_DomainTypeRegistration = 2, + mDNS_DomainTypeRegistrationDefault = 3 + } mDNS_DomainType; + +extern mStatus mDNS_GetDomains(mDNS *const m, DNSQuestion *const question, mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, mDNSQuestionCallback *Callback, void *Context); +// In the Panther mDNSResponder we don't do unicast queries yet, so there's no point trying to do domain enumeration +// mDNS_GetDomains() and mDNS_StopGetDomains() are set to be no-ops so that clients don't try to do browse/register operations that will fail +//#define mDNS_StopGetDomains mDNS_StopQuery +#define mDNS_StopGetDomains(m,q) ((void)(m),(void)(q)) +extern mStatus mDNS_AdvertiseDomains(mDNS *const m, AuthRecord *rr, mDNS_DomainType DomainType, const mDNSInterfaceID InterfaceID, char *domname); +#define mDNS_StopAdvertiseDomains mDNS_Deregister + +// *************************************************************************** +#if 0 +#pragma mark - DNS name utility functions +#endif + +// In order to expose the full capabilities of the DNS protocol (which allows any arbitrary eight-bit values +// in domain name labels, including unlikely characters like ascii nulls and even dots) all the mDNS APIs +// work with DNS's native length-prefixed strings. For convenience in C, the following utility functions +// are provided for converting between C's null-terminated strings and DNS's length-prefixed strings. + +// Assignment +// A simple C structure assignment of a domainname can cause a protection fault by accessing unmapped memory, +// because that object is defined to be 256 bytes long, but not all domainname objects are truly the full size. +// This macro uses mDNSPlatformMemCopy() to make sure it only touches the actual bytes that are valid. +#define AssignDomainName(DST, SRC) mDNSPlatformMemCopy((SRC).c, (DST).c, DomainNameLength(&(SRC))) + +// Comparison functions +extern mDNSBool SameDomainLabel(const mDNSu8 *a, const mDNSu8 *b); +extern mDNSBool SameDomainName(const domainname *const d1, const domainname *const d2); + +// Get total length of domain name, in native DNS format, including terminal root label +// (e.g. length of "com." is 5 (length byte, three data bytes, final zero) +extern mDNSu16 DomainNameLength(const domainname *const name); + +// Append functions to append one or more labels to an existing native format domain name: +// AppendLiteralLabelString adds a single label from a literal C string, with no escape character interpretation. +// AppendDNSNameString adds zero or more labels from a C string using conventional DNS dots-and-escaping interpretation +// AppendDomainLabel adds a single label from a native format domainlabel +// AppendDomainName adds zero or more labels from a native format domainname +extern mDNSu8 *AppendLiteralLabelString(domainname *const name, const char *cstr); +extern mDNSu8 *AppendDNSNameString (domainname *const name, const char *cstr); +extern mDNSu8 *AppendDomainLabel (domainname *const name, const domainlabel *const label); +extern mDNSu8 *AppendDomainName (domainname *const name, const domainname *const append); + +// Convert from null-terminated string to native DNS format: +// The DomainLabel form makes a single label from a literal C string, with no escape character interpretation. +// The DomainName form makes native format domain name from a C string using conventional DNS interpretation: +// dots separate labels, and within each label, '\.' represents a literal dot, '\\' represents a literal +// backslash and backslash with three decimal digits (e.g. \000) represents an arbitrary byte value. +extern mDNSBool MakeDomainLabelFromLiteralString(domainlabel *const label, const char *cstr); +extern mDNSu8 *MakeDomainNameFromDNSNameString (domainname *const name, const char *cstr); + +// Convert native format domainlabel or domainname back to C string format +// IMPORTANT: +// When using ConvertDomainLabelToCString, the target buffer must be MAX_ESCAPED_DOMAIN_LABEL (254) bytes long +// to guarantee there will be no buffer overrun. It is only safe to use a buffer shorter than this in rare cases +// where the label is known to be constrained somehow (for example, if the label is known to be either "_tcp" or "_udp"). +// Similarly, when using ConvertDomainNameToCString, the target buffer must be MAX_ESCAPED_DOMAIN_NAME (1005) bytes long. +// See definitions of MAX_ESCAPED_DOMAIN_LABEL and MAX_ESCAPED_DOMAIN_NAME for more detailed explanation. +extern char *ConvertDomainLabelToCString_withescape(const domainlabel *const name, char *cstr, char esc); +#define ConvertDomainLabelToCString_unescaped(D,C) ConvertDomainLabelToCString_withescape((D), (C), 0) +#define ConvertDomainLabelToCString(D,C) ConvertDomainLabelToCString_withescape((D), (C), '\\') +extern char *ConvertDomainNameToCString_withescape(const domainname *const name, char *cstr, char esc); +#define ConvertDomainNameToCString_unescaped(D,C) ConvertDomainNameToCString_withescape((D), (C), 0) +#define ConvertDomainNameToCString(D,C) ConvertDomainNameToCString_withescape((D), (C), '\\') + +extern void ConvertUTF8PstringToRFC1034HostLabel(const mDNSu8 UTF8Name[], domainlabel *const hostlabel); + +extern mDNSu8 *ConstructServiceName(domainname *const fqdn, const domainlabel *name, const domainname *type, const domainname *const domain); +extern mDNSBool DeconstructServiceName(const domainname *const fqdn, domainlabel *const name, domainname *const type, domainname *const domain); + +// Note: Some old functions have been replaced by more sensibly-named versions. +// You can uncomment the hash-defines below if you don't want to have to change your source code right away. +// When updating your code, note that (unlike the old versions) *all* the new routines take the target object +// as their first parameter. +//#define ConvertCStringToDomainName(SRC,DST) MakeDomainNameFromDNSNameString((DST),(SRC)) +//#define ConvertCStringToDomainLabel(SRC,DST) MakeDomainLabelFromLiteralString((DST),(SRC)) +//#define AppendStringLabelToName(DST,SRC) AppendLiteralLabelString((DST),(SRC)) +//#define AppendStringNameToName(DST,SRC) AppendDNSNameString((DST),(SRC)) +//#define AppendDomainLabelToName(DST,SRC) AppendDomainLabel((DST),(SRC)) +//#define AppendDomainNameToName(DST,SRC) AppendDomainName((DST),(SRC)) + +// *************************************************************************** +#if 0 +#pragma mark - Other utility functions +#endif + +extern mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, va_list arg); +extern mDNSu32 mDNS_snprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, ...) IS_A_PRINTF_STYLE_FUNCTION(3,4); +extern char *DNSTypeName(mDNSu16 rrtype); +extern char *GetRRDisplayString_rdb(mDNS *const m, const ResourceRecord *rr, RDataBody *rd); +#define GetRRDisplayString(m, rr) GetRRDisplayString_rdb((m), &(rr)->resrec, &(rr)->resrec.rdata->u) +extern mDNSBool mDNSSameAddress(const mDNSAddr *ip1, const mDNSAddr *ip2); +extern void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText); + +// *************************************************************************** +#if 0 +#pragma mark - PlatformSupport interface +#endif + +// This section defines the interface to the Platform Support layer. +// Normal client code should not use any of types defined here, or directly call any of the functions defined here. +// The definitions are placed here because sometimes clients do use these calls indirectly, via other supported client operations. +// For example, AssignDomainName is a macro defined using mDNSPlatformMemCopy() + +typedef packedstruct + { + mDNSOpaque16 id; + mDNSOpaque16 flags; + mDNSu16 numQuestions; + mDNSu16 numAnswers; + mDNSu16 numAuthorities; + mDNSu16 numAdditionals; + } DNSMessageHeader; + +// We can send and receive packets up to 9000 bytes (Ethernet Jumbo Frame size, if that ever becomes widely used) +// However, in the normal case we try to limit packets to 1500 bytes so that we don't get IP fragmentation on standard Ethernet +// 40 (IPv6 header) + 8 (UDP header) + 12 (DNS message header) + 1440 (DNS message body) = 1500 total +#define AbsoluteMaxDNSMessageData 8940 +#define NormalMaxDNSMessageData 1440 +typedef packedstruct + { + DNSMessageHeader h; // Note: Size 12 bytes + mDNSu8 data[AbsoluteMaxDNSMessageData]; // 40 (IPv6) + 8 (UDP) + 12 (DNS header) + 8940 (data) = 9000 + } DNSMessage; + +// Every platform support module must provide the following functions. +// mDNSPlatformInit() typically opens a communication endpoint, and starts listening for mDNS packets. +// When Setup is complete, the platform support layer calls mDNSCoreInitComplete(). +// mDNSPlatformSendUDP() sends one UDP packet +// When a packet is received, the PlatformSupport code calls mDNSCoreReceive() +// mDNSPlatformClose() tidies up on exit +// Note: mDNSPlatformMemAllocate/mDNSPlatformMemFree are only required for handling oversized resource records. +// If your target platform has a well-defined specialized application, and you know that all the records it uses +// are InlineCacheRDSize or less, then you can just make a simple mDNSPlatformMemAllocate() stub that always returns +// NULL. InlineCacheRDSize is a compile-time constant, which is set by default to 64. If you need to handle records +// a little larger than this and you don't want to have to implement run-time allocation and freeing, then you +// can raise the value of this constant to a suitable value (at the expense of increased memory usage). +extern mStatus mDNSPlatformInit (mDNS *const m); +extern void mDNSPlatformClose (mDNS *const m); +extern mStatus mDNSPlatformSendUDP(const mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, + mDNSInterfaceID InterfaceID, mDNSIPPort srcport, const mDNSAddr *dst, mDNSIPPort dstport); + +extern void mDNSPlatformLock (const mDNS *const m); +extern void mDNSPlatformUnlock (const mDNS *const m); + +extern void mDNSPlatformStrCopy (const void *src, void *dst); +extern mDNSu32 mDNSPlatformStrLen (const void *src); +extern void mDNSPlatformMemCopy (const void *src, void *dst, mDNSu32 len); +extern mDNSBool mDNSPlatformMemSame (const void *src, const void *dst, mDNSu32 len); +extern void mDNSPlatformMemZero ( void *dst, mDNSu32 len); +extern void * mDNSPlatformMemAllocate (mDNSu32 len); +extern void mDNSPlatformMemFree (void *mem); +extern mStatus mDNSPlatformTimeInit (mDNSs32 *timenow); + +// The core mDNS code provides these functions, for the platform support code to call at appropriate times +// +// mDNS_GenerateFQDN() is called once on startup (typically from mDNSPlatformInit()) +// and then again on each subsequent change of the dot-local host name. +// +// mDNS_RegisterInterface() is used by the platform support layer to inform mDNSCore of what +// physical and/or logical interfaces are available for sending and receiving packets. +// Typically it is called on startup for each available interface, but register/deregister may be +// called again later, on multiple occasions, to inform the core of interface configuration changes. +// If set->Advertise is set non-zero, then mDNS_RegisterInterface() also registers the standard +// resource records that should be associated with every publicised IP address/interface: +// -- Name-to-address records (A/AAAA) +// -- Address-to-name records (PTR) +// -- Host information (HINFO) +// +// mDNSCoreInitComplete() is called when the platform support layer is finished. +// Typically this is at the end of mDNSPlatformInit(), but may be later +// (on platforms like OT that allow asynchronous initialization of the networking stack). +// +// mDNSCoreReceive() is called when a UDP packet is received +// +// mDNSCoreMachineSleep() is called when the machine sleeps or wakes +// (This refers to heavyweight laptop-style sleep/wake that disables network access, +// not lightweight second-by-second CPU power management modes.) + +extern void mDNS_GenerateFQDN(mDNS *const m); +extern mStatus mDNS_RegisterInterface (mDNS *const m, NetworkInterfaceInfo *set); +extern void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set); +extern void mDNSCoreInitComplete(mDNS *const m, mStatus result); +extern void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNSu8 *const end, + const mDNSAddr *const srcaddr, const mDNSIPPort srcport, + const mDNSAddr *const dstaddr, const mDNSIPPort dstport, const mDNSInterfaceID InterfaceID, mDNSu8 ttl); +extern void mDNSCoreMachineSleep(mDNS *const m, mDNSBool wake); + +// *************************************************************************** +#if 0 +#pragma mark - Compile-Time assertion checks +#endif + +// Some C compiler cleverness. We can make the compiler check certain things for +// us, and report compile-time errors if anything is wrong. The usual way to do +// this would be to use a run-time "if" statement, but then you don't find out +// what's wrong until you run the software. This way, if the assertion condition +// is false, the array size is negative, and the complier complains immediately. + +struct mDNS_CompileTimeAssertionChecks + { + // Check that the compiler generated our on-the-wire packet format structure definitions + // properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries. + char assert0[(sizeof(rdataSRV) == 262 ) ? 1 : -1]; + char assert1[(sizeof(DNSMessageHeader) == 12 ) ? 1 : -1]; + char assert2[(sizeof(DNSMessage) == 12+AbsoluteMaxDNSMessageData) ? 1 : -1]; + char assert3[(sizeof(mDNSs8) == 1 ) ? 1 : -1]; + char assert4[(sizeof(mDNSu8) == 1 ) ? 1 : -1]; + char assert5[(sizeof(mDNSs16) == 2 ) ? 1 : -1]; + char assert6[(sizeof(mDNSu16) == 2 ) ? 1 : -1]; + char assert7[(sizeof(mDNSs32) == 4 ) ? 1 : -1]; + char assert8[(sizeof(mDNSu32) == 4 ) ? 1 : -1]; + char assert9[(sizeof(mDNSOpaque16) == 2 ) ? 1 : -1]; + char assertA[(sizeof(mDNSOpaque32) == 4 ) ? 1 : -1]; + char assertB[(sizeof(mDNSOpaque128) == 16 ) ? 1 : -1]; + }; + +// *************************************************************************** + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/mDNSMacOSX/CFSocket.c b/mDNSMacOSX/CFSocket.c index fb2e821..e4c230d 100644 --- a/mDNSMacOSX/CFSocket.c +++ b/mDNSMacOSX/CFSocket.c @@ -23,6 +23,9 @@ Change History (most recent first): $Log: CFSocket.c,v $ +Revision 1.115.2.5 2005/01/28 05:02:06 cheshire + SUPan: Replace IP TTL 255 check with local-subnet check + Revision 1.115.2.4 2004/04/23 00:34:06 cheshire : mDNSResponder messages on wake Take care to correctly update InterfaceIDs when a dormant interface comes back to life @@ -651,6 +654,7 @@ mDNSlocal void myCFSocketCallBack(CFSocketRef cfs, CFSocketCallBackType CallBack mDNSIPPort senderPort, destPort = MulticastDNSPort; NetworkInterfaceInfoOSX *info = (NetworkInterfaceInfoOSX *)context; mDNS *const m = info->m; + mDNSInterfaceID InterfaceID = info->ifinfo.InterfaceID; DNSMessage packet; struct sockaddr_storage from; size_t fromlen = sizeof(from); @@ -704,25 +708,38 @@ mDNSlocal void myCFSocketCallBack(CFSocketRef cfs, CFSocketCallBackType CallBack return; } - // Even though we indicated a specific interface in the IP_ADD_MEMBERSHIP call, a weirdness of the - // sockets API means that even though this socket has only officially joined the multicast group - // on one specific interface, the kernel will still deliver multicast packets to it no matter which - // interface they arrive on. According to the official Unix Powers That Be, this is Not A Bug. - // To work around this weirdness, we use the IP_RECVIF option to find the name of the interface - // on which the packet arrived, and ignore the packet if it really arrived on some other interface. - if (strcmp(info->ifa_name, packetifname)) + if (mDNSAddrIsDNSMulticast(&destAddr)) { - verbosedebugf("myCFSocketCallBack got a packet from %#a to %#a on interface %#a/%s (Ignored -- really arrived on interface %s)", - &senderAddr, &destAddr, &info->ifinfo.ip, info->ifa_name, packetifname); - return; + // Even though we indicated a specific interface in the IP_ADD_MEMBERSHIP call, a weirdness of the + // sockets API means that even though this socket has only officially joined the multicast group + // on one specific interface, the kernel will still deliver multicast packets to it no matter which + // interface they arrive on. According to the official Unix Powers That Be, this is Not A Bug. + // To work around this weirdness, we use the IP_RECVIF option to find the name of the interface + // on which the packet arrived, and ignore the packet if it really arrived on some other interface. + if (strcmp(info->ifa_name, packetifname)) + { + verbosedebugf("myCFSocketCallBack got a packet from %#a to %#a on interface %#a/%s (Ignored -- really arrived on interface %s)", + &senderAddr, &destAddr, &info->ifinfo.ip, info->ifa_name, packetifname); + return; + } + else + verbosedebugf("myCFSocketCallBack got a packet from %#a to %#a on interface %#a/%s", + &senderAddr, &destAddr, &info->ifinfo.ip, info->ifa_name); } else - verbosedebugf("myCFSocketCallBack got a packet from %#a to %#a on interface %#a/%s", - &senderAddr, &destAddr, &info->ifinfo.ip, info->ifa_name); + { + verbosedebugf("myCFSocketCallBack got a unicast from %#a to %#a on interface %#a/%s packetifname %s)", + &senderAddr, &destAddr, &info->ifinfo.ip, info->ifa_name, packetifname); + // Note: For unicast packets, try to find the matching mDNSCore interface object + // (though we may not be able to, for unicast packets received over something like a PPP link) + NetworkInterfaceInfo *intf = m->HostInterfaces; + while (intf && strcmp(intf->ifname, packetifname)) intf = intf->next; + if (intf) InterfaceID = intf->InterfaceID; + } if (err < (int)sizeof(DNSMessageHeader)) { debugf("myCFSocketCallBack packet length (%d) too short", err); return; } - mDNSCoreReceive(m, &packet, (unsigned char*)&packet + err, &senderAddr, senderPort, &destAddr, destPort, info->ifinfo.InterfaceID, ttl); + mDNSCoreReceive(m, &packet, (unsigned char*)&packet + err, &senderAddr, senderPort, &destAddr, destPort, InterfaceID, ttl); } if (err < 0 && (errno != EWOULDBLOCK || count == 0)) @@ -968,6 +985,9 @@ mDNSlocal mStatus AddInterfaceToList(mDNS *const m, struct ifaddrs *ifa) i->ifinfo.InterfaceID = mDNSNULL; i->ifinfo.ip = ip; + SetupAddr(&i->ifinfo.mask, ifa->ifa_netmask); + strncpy(i->ifinfo.ifname, ifa->ifa_name, sizeof(i->ifinfo.ifname)); + i->ifinfo.ifname[sizeof(i->ifinfo.ifname)-1] = 0; i->ifinfo.Advertise = m->AdvertiseLocalAddresses; i->ifinfo.TxAndRx = mDNSfalse; // For now; will be set up later at the end of UpdateInterfaceList diff --git a/mDNSMacOSX/daemon.c b/mDNSMacOSX/daemon.c index 51ab0f3..9710517 100644 --- a/mDNSMacOSX/daemon.c +++ b/mDNSMacOSX/daemon.c @@ -36,6 +36,13 @@ Change History (most recent first): $Log: daemon.c,v $ +Revision 1.134.2.8 2005/01/28 04:03:24 cheshire + SUPan: Current method of doing subtypes causes name collisions +Summary: Pulled in ConstructServiceName, CountSubTypes and AllocateSubTypes from Tiger version. + +Revision 1.134.2.7 2004/06/18 17:28:19 cheshire + Current method of doing subtypes causes name collisions + Revision 1.134.2.6 2004/04/06 19:50:36 cheshire mDNSResponder will not launch if "nobody" user doesn't exist. After more discussion, we've decided to use userid -2 if "nobody" user doesn't exist. @@ -224,6 +231,9 @@ Add $Log header #include "mDNSClientAPI.h" // Defines the interface to the client layer above #include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform +extern mDNSs32 CountSubTypes(char *regtype); +extern AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p); + #include #define ENABLE_UDS 1 @@ -712,7 +722,12 @@ mDNSexport kern_return_t provide_DNSServiceBrowserCreate_rpc(mach_port_t unuseds // Check other parameters domainname t, d; - if (!regtype[0] || !MakeDomainNameFromDNSNameString(&t, regtype)) { errormsg = "Illegal regtype"; goto badparam; } + t.c[0] = 0; + mDNSs32 NumSubTypes = CountSubTypes(regtype); + if (NumSubTypes < 0 || NumSubTypes > 1) { errormsg = "Bad Service SubType"; goto badparam; } + if (NumSubTypes == 1 && !AppendDNSNameString(&t, regtype + strlen(regtype) + 1)) + { errormsg = "Bad Service SubType"; goto badparam; } + if (!regtype[0] || !AppendDNSNameString(&t, regtype)) { errormsg = "Illegal regtype"; goto badparam; } if (!MakeDomainNameFromDNSNameString(&d, *domain ? domain : "local.")) { errormsg = "Illegal domain"; goto badparam; } // Allocate memory, and handle failure @@ -965,22 +980,8 @@ mDNSexport kern_return_t provide_DNSServiceRegistrationCreate_rpc(mach_port_t un if (CheckForExistingClient(client)) { err = mStatus_Invalid; errormsg = "Client id already in use"; goto fail; } // Check for sub-types after the service type - AuthRecord *SubTypes = mDNSNULL; - mDNSu32 i, NumSubTypes = 0; - char *comma = regtype; - while (*comma && *comma != ',') comma++; - if (*comma) // If we found a comma... - { - *comma = 0; // Overwrite the first comma with a nul - char *p = comma + 1; // Start scanning from the next character - while (*p) - { - if ( !(*p && *p != ',')) { errormsg = "Bad Service SubType"; goto badparam; } - while (*p && *p != ',') p++; - if (*p) *p++ = 0; - NumSubTypes++; - } - } + mDNSs32 NumSubTypes = CountSubTypes(regtype); + if (NumSubTypes < 0) { errormsg = "Bad Service SubType"; goto badparam; } // Check other parameters domainlabel n; @@ -1030,17 +1031,9 @@ mDNSexport kern_return_t provide_DNSServiceRegistrationCreate_rpc(mach_port_t un DNSServiceRegistration *x = mallocL("DNSServiceRegistration", sizeof(*x) - sizeof(RDataBody) + size); if (!x) { err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } - if (NumSubTypes) - { - SubTypes = mallocL("ServiceSubTypes", NumSubTypes * sizeof(AuthRecord)); - if (!SubTypes) { freeL("DNSServiceRegistration", x); err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } - for (i = 0; i < NumSubTypes; i++) - { - comma++; // Advance over the nul character - MakeDomainNameFromDNSNameString(&SubTypes[i].resrec.name, comma); - while (*comma) comma++; // Advance comma to point to the next terminating nul - } - } + AuthRecord *SubTypes = AllocateSubTypes(NumSubTypes, regtype); + if (NumSubTypes && !SubTypes) + { freeL("DNSServiceRegistration", x); err = mStatus_NoMemoryErr; errormsg = "No memory"; goto fail; } // Set up object, and link into list x->ClientMachPort = client; @@ -1062,7 +1055,7 @@ mDNSexport kern_return_t provide_DNSServiceRegistrationCreate_rpc(mach_port_t un mDNSNULL, port, // Host and port txtinfo, data_len, // TXT data, length SubTypes, NumSubTypes, // Subtypes - mDNSInterface_Any, // Interace ID + mDNSInterface_Any, // Interface ID RegCallback, x); // Callback and context if (err) { AbortClient(client, x); errormsg = "mDNS_RegisterService"; goto fail; } @@ -1094,6 +1087,7 @@ mDNSlocal void mDNS_StatusCallback(mDNS *const m, mStatus result) r->autorename = mDNStrue; mDNS_DeregisterService(&mDNSStorage, &r->s); } + udsserver_handle_configchange(); } else if (result == mStatus_GrowCache) { diff --git a/mDNSMacOSX/dns_sd.h b/mDNSMacOSX/dns_sd.h deleted file mode 100755 index eaed335..0000000 --- a/mDNSMacOSX/dns_sd.h +++ /dev/null @@ -1,1006 +0,0 @@ -/* - * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: dns_sd.h,v $ -Revision 1.3 2003/08/12 19:51:51 cheshire -Update to APSL 2.0 - - - */ - -#ifndef _DNS_SD_H -#define _DNS_SD_H - -#include -#include -#include -#include - - -/* DNSServiceRef, DNSRecordRef - * - * Opaque internal data types. - * Note: client is responsible for serializing access to these structures if - * they are shared between concurrent threads. - */ - -typedef struct _DNSServiceRef_t *DNSServiceRef; -typedef struct _DNSRecordRef_t *DNSRecordRef; - -/* General flags used in functions defined below */ -enum - { - kDNSServiceFlagsMoreComing = 1, - kDNSServiceFlagsFinished = 0, /* i.e. bit not set */ - /* MoreComing indicates to a Browse callback that another result is - * queued. Applications should not update their UI to display browse - * results when the MoreComing flag is set, instead deferring the update - * until the callback's flag is Finished. */ - - kDNSServiceFlagsAdd = 2, - kDNSServiceFlagsDefault = 4, - kDNSServiceFlagsRemove = 0, /* i.e. bit not set */ - /* Flags for domain enumeration and browse reply callbacks. - * "Default" applies only to enumeration and is only valid in - * conjuction with "Add" - */ - - kDNSServiceFlagsNoAutoRename = 8, - kDNSServiceFlagsAutoRename = 0, /* i.e. bit not set */ - /* Flag for specifying renaming behavior on name conflict when registering - * non-shared records. NoAutorename is only valid if a name is explicitly - * specified when registering a service (ie the default name is not used.) - */ - - - kDNSServiceFlagsShared = 16, - kDNSServiceFlagsUnique = 32, - /* Flag for registering individual records on a connected - * DNSServiceRef. Shared indicates that there may be multiple records - * with this name on the network (e.g. PTR records). Unique indicates that the - * record's name is to be unique on the network (e.g. SRV records). - */ - - kDNSServiceFlagsBrowseDomains = 64, - kDNSServiceFlagsRegistrationDomains = 128 - /* Flags for specifying domain enumeration type in DNSServiceEnumerateDomains. - * BrowseDomains enumerates domains recommended for browsing, RegistrationDomains - * enumerates domains recommended for registration. - */ - }; - -/* possible error code values */ -enum - { - kDNSServiceErr_NoError = 0, - kDNSServiceErr_Unknown = -65537, /* 0xFFFE FFFF */ - kDNSServiceErr_NoSuchName = -65538, - kDNSServiceErr_NoMemory = -65539, - kDNSServiceErr_BadParam = -65540, - kDNSServiceErr_BadReference = -65541, - kDNSServiceErr_BadState = -65542, - kDNSServiceErr_BadFlags = -65543, - kDNSServiceErr_Unsupported = -65544, - kDNSServiceErr_NotInitialized = -65545, - kDNSServiceErr_AlreadyRegistered = -65547, - kDNSServiceErr_NameConflict = -65548, - kDNSServiceErr_Invalid = -65549, - kDNSServiceErr_Incompatible = -65551, /* client library incompatible with daemon */ - kDNSServiceErr_BadinterfaceIndex = -65552 - /* mDNS Error codes are in the range - * FFFE FF00 (-65792) to FFFE FFFF (-65537) */ - }; - - -/* Maximum length, in bytes, of a domain name represented as an escaped C-String */ -#define kDNSServiceMaxDomainName 1005 - - -typedef uint32_t DNSServiceFlags; -typedef int32_t DNSServiceErrorType; - - -/********************************************************************************************* - * - * Unix Domain Socket access, DNSServiceRef deallocation, and data processing functions - * - *********************************************************************************************/ - - -/* DNSServiceRefSockFD() - * - * Access underlying Unix domain socket for an initialized DNSServiceRef. - * The DNS Service Discovery implmementation uses this socket to communicate between - * the client and the mDNSResponder daemon. The application MUST NOT directly read from - * or write to this socket. Access to the socket is provided so that it can be used as a - * run loop source, or in a select() loop: when data is available for reading on the socket, - * DNSServiceProcessResult() should be called, which will extract the daemon's reply from - * the socket, and pass it to the appropriate application callback. By using a run loop or - * select(), results from the daemon can be processed asynchronously. Without using these - * constructs, DNSServiceProcessResult() will block until the response from the daemon arrives. - * The client is responsible for ensuring that the data on the socket is processed in a timely - * fashion - the daemon may terminate its connection with a client that does not clear its - * socket buffer. - * - * sdRef: A DNSServiceRef initialized by any of the DNSService calls. - * - * return value: The DNSServiceRef's underlying socket descriptor, or -1 on - * error. - */ - -int DNSServiceRefSockFD(DNSServiceRef sdRef); - -/* DNSServiceProcessResult() - * - * Read a reply from the daemon, calling the appropriate application callback. This call will - * block until the daemon's response is received. Use DNSServiceRefSockFD() in - * conjunction with a run loop or select() to determine the presence of a response from the - * server before calling this function to process the reply without blocking. Call this function - * at any point if it is acceptable to block until the daemon's response arrives. Note that the - * client is responsible for ensuring that DNSServiceProcessResult() is called whenever there is - * a reply from the daemon - the daemon may terminate its connection with a client that does not - * process the daemon's responses. - * - * sdRef: A DNSServiceRef initialized by any of the DNSService calls - * that take a callback parameter. - * - * return value: Returns kDNSServiceErr_NoError on success, otherwise returns - * an error code indicating the specific failure that occurred. - */ - -DNSServiceErrorType DNSServiceProcessResult(DNSServiceRef sdRef); - -/* DNSServiceRefDeallocate() - * - * Terminate a connection with the daemon and free memory associated with the DNSServiceRef. - * Any services or records registered with this DNSServiceRef will be deregistered. Any - * Browse, Resolve, or Query operations called with this reference will be terminated. If the - * reference's underlying socket is used in a run loop or select() call, it should be removed BEFORE - * DNSServiceRefDeallocate() is called, as this function closes the reference's socket. - * - * Note: This call is to be used only with the DNSServiceRef defined by this API. It is - * not compatible with dns_service_discovery_ref objects defined in the legacy Mach-based - * DNSServiceDiscovery.h API. - * - * sdRef: A DNSServiceRef initialized by any of the DNSService calls. - * - */ - -void DNSServiceRefDeallocate(DNSServiceRef sdRef); - - -/********************************************************************************************* - * - * Domain Enumeration - * - *********************************************************************************************/ - -/* DNSServiceEnumerateDomains() - * - * Asynchronously enumerate domains available for browsing and registration. - * Currently, the only domain returned is "local.", but other domains will be returned in future. - * - * The enumeration MUST be cancelled via DNSServiceRefDeallocate() when no more domains - * are to be found. - * - * - * DNSServiceDomainEnumReply Callback Parameters: - * - * sdRef: The DNSServiceRef initialized by DNSServiceEnumerateDomains(). - * - * flags: Possible values are: - * 1 (MoreComing) - * 2 (Add/Remove) - * 4 (Add Default) - * - * interfaceIndex: Specifies the interface on which the domain exists. (The index for a given - * interface is determined via the if_nametoindex() family of calls.) - * - * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise indicates - * the failure that occurred (other parameters are undefined if errorCode is nonzero). - * - * replyDomain: The name of the domain. - * - * context: The context pointer passed to DNSServiceEnumerateDomains. - * - */ - -typedef void (*DNSServiceDomainEnumReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *replyDomain, - void *context - ); - -/* DNSServiceEnumerateDomains() Parameters: - * - * - * sdRef: A pointer to an uninitialized sdRef. May be passed to - * DNSServiceRefDeallocate() to cancel the enumeration. - * - * flags: Possible values are: - * 0 (BrowseDomains) to enumerate domains recommended for browsing. - * 32 (RegistrationDomains) to enumerate domains recommended for registration. - * - * interfaceIndex: If non-zero, specifies the interface on which to look for domains. - * (the index for a given interface is determined via the if_nametoindex() - * family of calls.) Most applications will pass 0 to enumerate domains on - * all interfaces. - * - * callBack: The function to be called when a domain is found or the call asynchronously - * fails. - * - * context: An application context pointer which is passed to the callback function - * (may be NULL). - * - * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating - * the error that occurred (the callback is not invoked and the DNSServiceRef - * is not initialized.) - */ - -DNSServiceErrorType DNSServiceEnumerateDomains - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceDomainEnumReply callBack, - void *context /* may be NULL */ - ); - -/********************************************************************************************* - * - * Service Registration - * - *********************************************************************************************/ - -/* Register a service that is discovered via Browse() and Resolve() calls. - * - * - * DNSServiceRegisterReply() Callback Parameters: - * - * sdRef: The DNSServiceRef initialized by DNSServiceRegister(). - * - * flags: Currently unused, reserved for future use. - * - * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will - * indicate the failure that occurred (including name conflicts, if the - * kDNSServiceFlagsNoAutoRenameOnConflict flag was passed to the - * callout.) Other parameters are undefined if errorCode is nonzero. - * - * name: The service name registered (if the application did not specify a name in - * DNSServiceRegister(), this indicates what name was automatically chosen). - * - * regtype: The type of service registered, as it was passed to the callout. - * - * domain: The domain on which the service was registered (if the application did not - * specify a domain in DNSServiceRegister(), this indicates the default domain - * on which the service was registered). - * - * context: The context pointer that was passed to the callout. - * - */ - -typedef void (*DNSServiceRegisterReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - DNSServiceErrorType errorCode, - const char *name, - const char *regtype, - const char *domain, - void *context - ); - -/* DNSServiceRegister() Parameters: - * - * sdRef: A pointer to an uninitialized sdRef. If this call succeeds, the reference - * may be passed to - * DNSServiceRefDeallocate() to deregister the service. - * - * interfaceIndex: If non-zero, specifies the interface on which to register the service - * (the index for a given interface is determined via the if_nametoindex() - * family of calls.) Most applications will pass 0 to register on all - * available interfaces. Pass -1 to register a service only on the local - * machine (service will not be visible to remote hosts.) - * - * flags: Indicates the renaming behavior on name conflict (most applications - * will pass 0). See flag definitions above for details. - * - * name: If non-NULL, specifies the service name to be registered. - * Most applications will not specify a name, in which case the - * computer name is used (this name is communicated to the client via - * the callback). - * - * regtype: The service type followed by the protocol, separated by a dot - * (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". - * - * domain: If non-NULL, specifies the domain on which to advertise the service. - * Most applications will not specify a domain, instead automatically - * registering in the default domain(s). - * - * host: If non-NULL, specifies the SRV target host name. Most applications - * will not specify a host, instead automatically using the machine's - * default host name(s). Note that specifying a non-NULL host does NOT - * create an address record for that host - the application is responsible - * for ensuring that the appropriate address record exists, or creating it - * via DNSServiceRegisterRecord(). - * - * port: The port on which the service accepts connections. Pass 0 for a - * "placeholder" service (i.e. a service that will not be discovered by - * browsing, but will cause a name conflict if another client tries to - * register that same name.) Most clients will not use placeholder services. - * - * txtLen: The length of the txtRecord, in bytes. Must be zero if the txtRecord is NULL. - * - * txtRecord: The txt record rdata. May be NULL. Note that a non-NULL txtRecord - * MUST be a properly formatted DNS TXT record, i.e. - * ... - * - * callBack: The function to be called when the registration completes or asynchronously - * fails. The client MAY pass NULL for the callback - The client will NOT be notified - * of the default values picked on its behalf, and the client will NOT be notified of any - * asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration - * of the service. The client may NOT pass the NoAutoRename flag if the callback is NULL. - * The client may still deregister the service at any time via DNSServiceRefDeallocate(). - * - * context: An application context pointer which is passed to the callback function - * (may be NULL). - * - * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating - * the error that occurred (the callback is never invoked and the DNSServiceRef - * is not initialized.) - * - */ - -DNSServiceErrorType DNSServiceRegister - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *name, /* may be NULL */ - const char *regtype, - const char *domain, /* may be NULL */ - const char *host, /* may be NULL */ - uint16_t port, - uint16_t txtLen, - const void *txtRecord, /* may be NULL */ - DNSServiceRegisterReply callBack, /* may be NULL */ - void *context /* may be NULL */ - ); - -/* DNSServiceAddRecord() - * - * Add a record to a registered service. The name of the record will be the same as the - * registered service's name. - * The record can later be updated or deregistered by passing the RecordRef initialized - * by this function to DNSServiceUpdateRecord() or DNSServiceRemoveRecord(). - * - * - * Parameters; - * - * sdRef: A DNSServiceRef initialized by DNSServiceRegister(). - * - * RecordRef: A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this - * call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord(). - * - * flags: Currently ignored, reserved for future use. - * - * rrtype: The type of the record (e.g. TXT, SRV, etc), as defined in nameser.h. - * - * rdlen: The length, in bytes, of the rdata. - * - * rdata: The raw rdata to be contained in the added resource record. - * - * ttl: The time to live of the resource record, in seconds. - * - * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an - * error code indicating the error that occurred (the RecordRef is not initialized). - */ - -DNSServiceErrorType DNSServiceAddRecord - ( - DNSServiceRef sdRef, - DNSRecordRef *RecordRef, - DNSServiceFlags flags, - uint16_t rrtype, - uint16_t rdlen, - const void *rdata, - uint32_t ttl - ); - -/* DNSServiceUpdateRecord - * - * Update a registered resource record. The record must either be: - * - The primary txt record of a service registered via DNSServiceRegister() - * - A record added to a registered service via DNSServiceAddRecord() - * - An individual record registered by DNSServiceRegisterRecord() - * - * - * Parameters: - * - * sdRef: A DNSServiceRef that was initialized by DNSServiceRegister() - * or DNSServiceCreateConnection(). - * - * RecordRef: A DNSRecordRef initialized by DNSServiceAddRecord, or NULL to update the - * service's primary txt record. - * - * flags: Currently ignored, reserved for future use. - * - * rdlen: The length, in bytes, of the new rdata. - * - * rdata: The new rdata to be contained in the updated resource record. - * - * ttl: The time to live of the updated resource record, in seconds. - * - * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an - * error code indicating the error that occurred. - */ - -DNSServiceErrorType DNSServiceUpdateRecord - ( - DNSServiceRef sdRef, - DNSRecordRef RecordRef, /* may be NULL */ - DNSServiceFlags flags, - uint16_t rdlen, - const void *rdata, - uint32_t ttl - ); - -/* DNSServiceRemoveRecord - * - * Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister - * an record registered individually via DNSServiceRegisterRecord(). - * - * Parameters: - * - * sdRef: A DNSServiceRef initialized by DNSServiceRegister() (if the - * record being removed was registered via DNSServiceAddRecord()) or by - * DNSServiceCreateConnection() (if the record being removed was registered via - * DNSServiceRegisterRecord()). - * - * recordRef: A DNSRecordRef initialized by a successful call to DNSServiceAddRecord() - * or DNSServiceRegisterRecord(). - * - * flags: Currently ignored, reserved for future use. - * - * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an - * error code indicating the error that occurred. - */ - -DNSServiceErrorType DNSServiceRemoveRecord - ( - DNSServiceRef sdRef, - DNSRecordRef RecordRef, - DNSServiceFlags flags - ); - - -/********************************************************************************************* - * - * Service Discovery - * - *********************************************************************************************/ - - -/* Browse for instances of a service. - * - * - * DNSServiceBrowseReply() Parameters: - * - * sdRef: The DNSServiceRef initialized by DNSServiceBrowse(). - * - * flags: Possible values are MoreComing and Add/Remove. See flag definitions - * for details. - * - * interfaceIndex: The interface on which the service is advertised. This index should - * be passed to DNSServiceResolve() when resolving the service. - * - * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will - * indicate the failure that occurred. Other parameters are undefined if - * the errorCode is nonzero. - * - * serviceName: The service name discovered. - * - * regtype: The service type, as passed in to DNSServiceBrowse(). - * - * domain: The domain on which the service was discovered (if the application did not - * specify a domain in DNSServicBrowse(), this indicates the domain on which the - * service was discovered.) - * - * context: The context pointer that was passed to the callout. - * - */ - -typedef void (*DNSServiceBrowseReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *serviceName, - const char *regtype, - const char *replyDomain, - void *context - ); - -/* DNSServiceBrowse() Parameters: - * - * sdRef: A pointer to an uninitialized sdRef. May be passed to - * DNSServiceRefDeallocate() to terminate the browse. - * - * flags: Currently ignored, reserved for future use. - * - * interfaceIndex: If non-zero, specifies the interface on which to browse for services - * (the index for a given interface is determined via the if_nametoindex() - * family of calls.) Most applications will pass 0 to browse on all available - * interfaces. Pass -1 to only browse for services provided on the local host. - * - * regtype: The service type being browsed for followed by the protocol, separated by a - * dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". - * - * domain: If non-NULL, specifies the domain on which to browse for services. - * Most applications will not specify a domain, instead browsing on the - * default domain(s). - * - * callBack: The function to be called when an instance of the service being browsed for - * is found, or if the call asynchronously fails. - * - * context: An application context pointer which is passed to the callback function - * (may be NULL). - * - * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating - * the error that occurred (the callback is not invoked and the DNSServiceRef - * is not initialized.) - */ - -DNSServiceErrorType DNSServiceBrowse - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *regtype, - const char *domain, /* may be NULL */ - DNSServiceBrowseReply callBack, - void *context /* may be NULL */ - ); - -/* DNSServiceResolve() - * - * Resolve a service name discovered via DNSServiceBrowse() to a target host name, port number, and - * txt record. - * - * Note: Applications should NOT use DNSServiceResolve() solely for txt record monitoring - use - * DNSServiceQueryRecord() instead, as it is more efficient for this task. - * - * Note: When the desired results have been returned, the client MUST terminate the resolve by calling - * DNSServiceRefDeallocate(). - * - * Note: DNSServiceResolve() behaves correctly for typical services that have a single SRV record and - * a single TXT record (the TXT record may be empty.) To resolve non-standard services with multiple - * SRV or TXT records, DNSServiceQueryRecord() should be used. - * - * DNSServiceResolveReply Callback Parameters: - * - * sdRef: The DNSServiceRef initialized by DNSServiceResolve(). - * - * flags: Possible values are MoreComing and Add/Remove. See flag definitions - * for details. - * - * interfaceIndex: The interface on which the service was resolved. - * - * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will - * indicate the failure that occurred. Other parameters are undefined if - * the errorCode is nonzero. - * - * fullname: The full service domain name, in the form ... - * (Any literal dots (".") are escaped with a backslash ("\."), and literal - * backslashes are escaped with a second backslash ("\\"), e.g. a web server - * named "Dr. Pepper" would have the fullname "Dr\.\032Pepper._http._tcp.local."). - * This is the appropriate format to pass to standard system DNS APIs such as - * res_query(), or to the special-purpose functions included in this API that - * take fullname parameters. - * - * hosttarget: The target hostname of the machine providing the service. This name can - * be passed to functions like gethostbyname() to identify the host's IP address. - * - * port: The port number on which connections are accepted for this service. - * - * txtLen: The length of the txt record, in bytes. - * - * txtRecord: The service's primary txt record, in standard txt record format. - * - - * context: The context pointer that was passed to the callout. - * - */ - -typedef void (*DNSServiceResolveReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *fullname, - const char *hosttarget, - uint16_t port, - uint16_t txtLen, - const char *txtRecord, - void *context - ); - -/* DNSServiceResolve() Parameters - * - * sdRef: A pointer to an uninitialized sdRef. May be passed to - * DNSServiceRefDeallocate() to terminate the resolve. - * - * flags: Currently ignored, reserved for future use. - * - * interfaceIndex: The interface on which to resolve the service. The client should - * pass the interface on which the servicename was discovered, i.e. - * the interfaceIndex passed to the DNSServiceBrowseReply callback, - * or 0 to resolve the named service on all available interfaces. - * - * name: The servicename to be resolved. - * - * regtype: The service type being resolved followed by the protocol, separated by a - * dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". - * - * domain: The domain on which the service is registered, i.e. the domain passed - * to the DNSServiceBrowseReply callback. - * - * callBack: The function to be called when a result is found, or if the call - * asynchronously fails. - * - * context: An application context pointer which is passed to the callback function - * (may be NULL). - * - * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating - * the error that occurred (the callback is never invoked and the DNSServiceRef - * is not initialized.) - */ - - -DNSServiceErrorType DNSServiceResolve - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *name, - const char *regtype, - const char *domain, - DNSServiceResolveReply callBack, - void *context /* may be NULL */ - ); - - -/********************************************************************************************* - * - * Special Purpose Calls (most applications will not use these) - * - *********************************************************************************************/ - -/* DNS Naming Conventions: - * - * The following functions refer to resource records by their full domain name, unlike the above - * functions which divide the name into servicename/regtype/domain fields. In the above functions, - * a dot (".") is considered to be a literal dot in the servicename field (e.g. "Dr. Pepper") and - * a label separator in the regtype ("_ftp._tcp") or domain ("apple.com") fields. Literal dots in - * the domain field would be escaped with a backslash, and literal backslashes would be escaped with - * a second backslash (this is generally not an issue, as domain names on the Internet today almost - * never use characters other than letters, digits, or hyphens, and the dots are label separators.) - * Furthermore, this is transparent to the caller, so long as the fields are passed between functions - * without manipulation. However, the following, special-purpose calls use a single, full domain name. - * As such, all dots are considered to be label separators, unless escaped, and all backslashes are - * considered to be escape characters, unless preceded by a second backslash. For example, the name - * "Dr. Smith \ Dr. Johnson" could be passed literally as a service name parameter in the above calls, - * but in the special purpose call, the dots and backslash would have to be escaped - * (e.g. "Dr\. Smith \\ Dr\. Johnson._ftp._tcp.apple.com" for an ftp service on the apple.com domain.) - */ - -/* DNSServiceConstructFullName() - * - * Concatenate a three-part domain name (as returned by the above callbacks) into a properly-escaped - * full domain name. Note that callbacks in the above functions ALREADY ESCAPE strings where necessary. - * - * Parameters: - * - * fullName: A pointer to a buffer that where the resulting full domain name is to be written. - * The buffer must be kDNSServiceDiscoveryMaxDomainName (1005) bytes in length to - * accommodate the longest legal domain name without buffer overrun. - * - * service: The service name - any dots or slashes must NOT be escaped. - * May be NULL (to construct a PTR record name, e.g. - * "_ftp._tcp.apple.com"). - * - * regtype: The service type followed by the protocol, separated by a dot - * (e.g. "_ftp._tcp"). - * - * domain: The domain name, e.g. "apple.com". Any literal dots or backslashes - * must be escaped. - * - * return value: Returns 0 on success, -1 on error. - * - */ - -int DNSServiceConstructFullName - ( - char *fullName, - const char *service, /* may be NULL */ - const char *regtype, - const char *domain - ); - -/* DNSServiceCreateConnection() - * - * Create a connection to the daemon allowing efficient registration of - * multiple individual records. - * - * - * Parameters: - * - * sdRef: A pointer to an uninitialized DNSServiceRef. Deallocating - * the reference (via DNSServiceRefDeallocate()) severs the - * connection and deregisters all records registered on this connection. - * - * return value: Returns kDNSServiceErr_NoError on success, otherwise returns - * an error code indicating the specific failure that occurred (in which - * case the DNSServiceRef is not initialized). - */ - -DNSServiceErrorType DNSServiceCreateConnection(DNSServiceRef *sdRef); - - -/* DNSServiceRegisterRecord - * - * Register an individual resource record on a connected DNSServiceRef. - * - * Note that name conflicts occurring for records registered via this call must be handled - * by the client in the callback. - * - * - * DNSServiceRegisterRecordReply() parameters: - * - * sdRef: The connected DNSServiceRef initialized by - * DNSServiceDiscoveryConnect(). - * - * RecordRef: The DNSRecordRef initialized by DNSServiceRegisterRecord(). - * - * flags: Currently unused, reserved for future use. - * - * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will - * indicate the failure that occurred (including name conflicts.) - * Other parameters are undefined if errorCode is nonzero. - * - * context: The context pointer that was passed to the callout. - * - */ - - typedef void (*DNSServiceRegisterRecordReply) - ( - DNSServiceRef sdRef, - DNSRecordRef RecordRef, - DNSServiceFlags flags, - DNSServiceErrorType errorCode, - void *context - ); - - -/* DNSServiceRegisterRecord() Parameters: - * - * sdRef: A DNSServiceRef initialized by DNSServiceCreateConnection(). - * - * RecordRef: A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this - * call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord(). - * (To deregister ALL records registered on a single connected DNSServiceRef - * and deallocate each of their corresponding DNSServiceRecordRefs, call - * DNSServiceRefDealloocate()). - * - * flags: Possible values are Shared/Unique (see flag type definitions for details). - * - * interfaceIndex: If non-zero, specifies the interface on which to register the record - * (the index for a given interface is determined via the if_nametoindex() - * family of calls.) Passing 0 causes the record to be registered on all interfaces. - * Passing -1 causes the record to only be visible on the local host. - * - * fullname: The full domain name of the resource record. - * - * rrtype: The numerical type of the resource record (e.g. PTR, SRV, etc), as defined - * in nameser.h. - * - * rrclass: The class of the resource record, as defined in nameser.h (usually 1 for the - * Internet class). - * - * rdlen: Length, in bytes, of the rdata. - * - * rdata: A pointer to the raw rdata, as it is to appear in the DNS record. - * - * ttl: The time to live of the resource record, in seconds. - * - * callBack: The function to be called when a result is found, or if the call - * asynchronously fails (e.g. because of a name conflict.) - * - * context: An application context pointer which is passed to the callback function - * (may be NULL). - * - * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating - * the error that occurred (the callback is never invoked and the DNSRecordRef is - * not initialized.) - */ - - -DNSServiceErrorType DNSServiceRegisterRecord - ( - DNSServiceRef sdRef, - DNSRecordRef *RecordRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - uint16_t rdlen, - const void *rdata, - uint32_t ttl, - DNSServiceRegisterRecordReply callBack, - void *context /* may be NULL */ - ); - - -/* DNSServiceQueryRecord - * - * Query for an arbitrary DNS record. - * - * - * DNSServiceQueryRecordReply() Callback Parameters: - * - * sdRef: The DNSServiceRef initialized by DNSServiceQueryRecord(). - * - * flags: Possible values are Finished/MoreComing. - * - * interfaceIndex: The interface on which the query was resolved (the index for a given - * interface is determined via the if_nametoindex() family of calls). - * - * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will - * indicate the failure that occurred. Other parameters are undefined if - * errorCode is nonzero. - * - * fullname: The resource record's full domain name. - * - * rrtype: The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h. - * - * rrclass: The class of the resource record, as defined in nameser.h (usually 1). - * - * rdlen: The length, in bytes, of the resource record rdata. - * - * rdata: The raw rdata of the resource record. - * - * ttl: The resource record's time to live, in seconds. - * - * context: The context pointer that was passed to the callout. - * - */ - -typedef void (*DNSServiceQueryRecordReply) - ( - DNSServiceRef DNSServiceRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - uint16_t rdlen, - const void *rdata, - uint32_t ttl, - void *context - ); - -/* DNSServiceQueryRecord() Parameters: - * - * sdRef: A pointer to an uninitialized DNSServiceRef. - * - * flags: Currently unused, reserved for future use. - * - * interfaceIndex: If non-zero, specifies the interface on which to issue the query - * (the index for a given interface is determined via the if_nametoindex() - * family of calls.) Passing 0 causes the name to be queried for on all - * interfaces. Passing -1 causes the name to be queried for only on the - * local host. - * - * fullname: The full domain name of the resource record to be queried for. - * - * rrtype: The numerical type of the resource record to be queried for (e.g. PTR, SRV, etc) - * as defined in nameser.h. - * - * rrclass: The class of the resource record, as defined in nameser.h - * (usually 1 for the Internet class). - * - * callBack: The function to be called when a result is found, or if the call - * asynchronously fails. - * - * context: An application context pointer which is passed to the callback function - * (may be NULL). - * - * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating - * the error that occurred (the callback is never invoked and the DNSServiceRef - * is not initialized.) - */ - -DNSServiceErrorType DNSServiceQueryRecord - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - DNSServiceQueryRecordReply callBack, - void *context /* may be NULL */ - ); - -/* DNSServiceReconfirmRecord - * - * Instruct the daemon to verify the validity of a resource record that appears to - * be out of date (e.g. because tcp connection to a service's target failed.) - * Causes the record to be flushed from the daemon's cache (as well as all other - * daemons' caches on the network) if the record is determined to be invalid. - * - * Parameters: - * - * flags: Currently unused, reserved for future use. - * - * fullname: The resource record's full domain name. - * - * rrtype: The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h. - * - * rrclass: The class of the resource record, as defined in nameser.h (usually 1). - * - * rdlen: The length, in bytes, of the resource record rdata. - * - * rdata: The raw rdata of the resource record. - * - */ - -void DNSServiceReconfirmRecord - ( - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - uint16_t rdlen, - const void *rdata - ); - - -#endif // _DNS_SD_H - diff --git a/mDNSMacOSX/mDNSMacOSX.c b/mDNSMacOSX/mDNSMacOSX.c new file mode 100644 index 0000000..4276c86 --- /dev/null +++ b/mDNSMacOSX/mDNSMacOSX.c @@ -0,0 +1,1494 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: mDNSMacOSX.c,v $ +Revision 1.115.2.4 2004/04/23 00:34:06 cheshire +: mDNSResponder messages on wake +Take care to correctly update InterfaceIDs when a dormant interface comes back to life + +Revision 1.115.2.3 2004/04/08 23:18:11 cheshire + When interface turned off, browse "remove" events delivered with interface index zero +Refinement from Bob Bradley: Should use "mDNS *const m" instead of referencing mDNSStorage directly + +Revision 1.115.2.2 2004/04/08 00:42:37 cheshire + When interface turned off, browse "remove" events delivered with interface index zero +Unify use of the InterfaceID field, and make code that walks the list respect the CurrentlyActive flag + +Revision 1.115.2.1 2004/04/07 01:08:15 cheshire + When interface turned off, browse "remove" events delivered with interface index zero + +Revision 1.115 2003/09/10 00:45:55 cheshire + Don't log "sendto failed" errors during the first two minutes of startup + +Revision 1.114 2003/08/27 02:55:13 cheshire +: Bug: Don't report mDNSPlatformSendUDP sendto errno 64 (Host is down) + +Revision 1.113 2003/08/19 22:20:00 cheshire + Don't use IPv6 on interfaces that have a routable IPv4 address configured +More minor refinements + +Revision 1.112 2003/08/19 03:04:43 cheshire + Don't use IPv6 on interfaces that have a routable IPv4 address configured + +Revision 1.111 2003/08/18 22:53:37 cheshire + mDNSResponder divide by zero in mDNSPlatformTimeNow() + +Revision 1.110 2003/08/16 03:39:00 cheshire + InterfaceID -1 indicates "local only" + +Revision 1.109 2003/08/15 02:19:49 cheshire + syslog messages: myCFSocketCallBack recvfrom skt 6 error -1 errno 35 +Also limit number of messages to at most 100 + +Revision 1.108 2003/08/12 22:24:52 cheshire + syslog messages: myCFSocketCallBack recvfrom skt 6 error -1 errno 35 +This message indicates a kernel bug, but still we don't want to flood syslog. +Do a sleep(1) after writing this log message, to limit the rate. + +Revision 1.107 2003/08/12 19:56:25 cheshire +Update to APSL 2.0 + +Revision 1.106 2003/08/12 13:48:32 cheshire +Add comment explaining clockdivisor calculation + +Revision 1.105 2003/08/12 13:44:14 cheshire + mDNSResponder *VERY* unhappy if time goes backwards +Use mach_absolute_time() (which is guaranteed to always go forwards, resetting only on reboot) +instead of gettimeofday() (which can jump back if the user manually changes their time/date) + +Revision 1.104 2003/08/12 13:12:07 cheshire +Textual search/replace: Indicate local functions using "mDNSlocal" instead of "static" + +Revision 1.103 2003/08/08 18:36:04 cheshire + Only need to revalidate on interface removal on platforms that have the PhantomInterfaces bug + +Revision 1.102 2003/08/06 00:14:52 cheshire + Need to check IP TTL on responses +Also add corresponding checks in the IPv6 code path + +Revision 1.101 2003/08/05 22:20:16 cheshire + Need to check IP TTL on responses + +Revision 1.100 2003/08/05 21:18:50 cheshire + mDNSResponder should ignore 6to4 +Only use interfaces that are marked as multicast-capable (IFF_MULTICAST) + +Revision 1.99 2003/08/05 20:13:52 cheshire + mDNSResponder using IPv6 interfaces before they are ready +Ignore interfaces with the IN6_IFF_NOTREADY flag set + +Revision 1.98 2003/07/20 03:38:51 ksekar +Bug #: 3320722 +Completed support for Unix-domain socket based API. + +Revision 1.97 2003/07/19 03:15:16 cheshire +Add generic MemAllocate/MemFree prototypes to mDNSPlatformFunctions.h, +and add the obvious trivial implementations to each platform support layer + +Revision 1.96 2003/07/18 00:30:00 cheshire + Remove mDNSResponder version from packet header and use HINFO record instead + +Revision 1.95 2003/07/12 03:15:20 cheshire + After SCDynamicStore notification, mDNSResponder updates +m->hostlabel even if user hasn't actually actually changed their dot-local hostname + +Revision 1.94 2003/07/03 00:51:54 cheshire + When select() and recvmgs() disagree, get more info from kernel about the socket state + +Revision 1.93 2003/07/03 00:09:14 cheshire + New APIs require a mDNSPlatformInterfaceIDfromInterfaceIndex() call +Additional refinement suggested by Josh: Use info->scope_id instead of if_nametoindex(info->ifa_name); + +Revision 1.92 2003/07/02 21:19:51 cheshire + Update copyright notices, etc., in source code comments + +Revision 1.91 2003/06/24 01:53:51 cheshire +Minor update to comments + +Revision 1.90 2003/06/24 01:51:47 cheshire + Oops: Double-dispose of sockets +Don't need to close sockets: CFSocketInvalidate() does that for us + +Revision 1.89 2003/06/21 18:12:47 cheshire + Rendezvous cannot handle interfaces whose total name is >3 chars +One-line change: should say "IF_NAMESIZE", not sizeof(ifname) + +Revision 1.88 2003/06/12 23:38:37 cheshire + mDNSResponder doesn't detect some configuration changes +Also check that scope_id matches before concluding that two interfaces are the same + +Revision 1.87 2003/06/10 01:14:11 cheshire + New APIs require a mDNSPlatformInterfaceIDfromInterfaceIndex() call + +Revision 1.86 2003/05/28 02:41:52 cheshire + Time to remove Mac OS 9 UDP Port 53 legacy support + +Revision 1.85 2003/05/28 02:39:47 cheshire +Minor change to debugging messages + +Revision 1.84 2003/05/27 22:29:40 cheshire +Remove out-dated comment + +Revision 1.83 2003/05/26 03:21:29 cheshire +Tidy up address structure naming: +mDNSIPAddr => mDNSv4Addr (for consistency with mDNSv6Addr) +mDNSAddr.addr.ipv4 => mDNSAddr.ip.v4 +mDNSAddr.addr.ipv6 => mDNSAddr.ip.v6 + +Revision 1.82 2003/05/26 03:01:27 cheshire + sprintf/vsprintf-style functions are unsafe; use snprintf/vsnprintf instead + +Revision 1.81 2003/05/24 02:06:42 cheshire + IPv6 Multicast Loopback doesn't work +Tried setting IPV6_MULTICAST_LOOP; it doesn't help. +However, it is probably wise to have the code explicitly set this socket +option anyway, in case the default changes in later versions of Unix. + +Revision 1.80 2003/05/24 02:02:24 cheshire + if_indextoname consumes a lot of CPU +Fix error in myIfIndexToName; was returning prematurely + +Revision 1.79 2003/05/23 23:07:44 cheshire + Must not write to stderr when running as daemon + +Revision 1.78 2003/05/23 01:19:04 cheshire + mDNSResponder needs to signal type of service to AirPort +Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate + +Revision 1.77 2003/05/23 01:12:05 cheshire +Minor code tidying + +Revision 1.76 2003/05/22 01:26:01 cheshire +Tidy up log messages + +Revision 1.75 2003/05/22 00:07:09 cheshire + myCFSocketCallBack recvfrom(5) error 1, errno 35 +Extra logging to determine whether there is a bug in CFSocket + +Revision 1.74 2003/05/21 20:20:12 cheshire +Fix warnings (mainly printf format string warnings, like using "%d" where +it should say "%lu", etc.) and improve error logging (use strerror() +to include textual error message as well as numeric error in log messages). + +Revision 1.73 2003/05/21 17:56:29 ksekar +Bug #: : mDNSResponder doesn't watch for IPv6 address changes + +Revision 1.72 2003/05/14 18:48:41 cheshire + mDNSResponder should be smarter about reconfigurations +More minor refinements: +CFSocket.c needs to do *all* its mDNS_DeregisterInterface calls before freeing memory +mDNS_DeregisterInterface revalidates cache record when *any* representative of an interface goes away + +Revision 1.71 2003/05/14 07:08:37 cheshire + mDNSResponder should be smarter about reconfigurations +Previously, when there was any network configuration change, mDNSResponder +would tear down the entire list of active interfaces and start again. +That was very disruptive, and caused the entire cache to be flushed, +and caused lots of extra network traffic. Now it only removes interfaces +that have really gone, and only adds new ones that weren't there before. + +Revision 1.70 2003/05/07 18:30:24 cheshire +Fix signed/unsigned comparison warning + +Revision 1.69 2003/05/06 20:14:44 cheshire +Change "tp" to "tv" + +Revision 1.68 2003/05/06 00:00:49 cheshire + Rationalize naming of domainname manipulation functions + +Revision 1.67 2003/04/29 00:43:44 cheshire +Fix compiler warnings + +Revision 1.66 2003/04/26 02:41:58 cheshire + Change timenow from a local variable to a structure member + +Revision 1.65 2003/04/26 02:34:01 cheshire +Add missing mDNSexport + +Revision 1.64 2003/04/15 16:48:06 jgraessl +Bug #: 3228833 +Modified code in CFSocket notifier function to read all packets on the socket +instead of reading only one packet every time the notifier was called. + +Revision 1.63 2003/04/15 16:33:50 jgraessl +Bug #: 3221880 +Switched to our own copy of if_indextoname to improve performance. + +Revision 1.62 2003/03/28 01:55:44 cheshire +Minor improvements to debugging messages + +Revision 1.61 2003/03/27 03:30:56 cheshire + Name conflicts not handled properly, resulting in memory corruption, and eventual crash +Problem was that HostNameCallback() was calling mDNS_DeregisterInterface(), which is not safe in a callback +Fixes: +1. Make mDNS_DeregisterInterface() safe to call from a callback +2. Make HostNameCallback() use mDNS_DeadvertiseInterface() instead + (it never really needed to deregister the interface at all) + +Revision 1.60 2003/03/15 04:40:38 cheshire +Change type called "mDNSOpaqueID" to the more descriptive name "mDNSInterfaceID" + +Revision 1.59 2003/03/11 01:23:26 cheshire +Bug #: 3194246 mDNSResponder socket problems + +Revision 1.58 2003/03/06 01:43:04 cheshire +Bug #: 3189097 Additional debugging code in mDNSResponder +Improve "LIST_ALL_INTERFACES" output + +Revision 1.57 2003/03/05 22:36:27 cheshire +Bug #: 3186338 Loopback doesn't work with mDNSResponder-27 +Temporary workaround: Skip loopback interface *only* if we found at least one v4 interface to use + +Revision 1.56 2003/03/05 01:50:38 cheshire +Bug #: 3189097 Additional debugging code in mDNSResponder + +Revision 1.55 2003/02/21 01:54:09 cheshire +Bug #: 3099194 mDNSResponder needs performance improvements +Switched to using new "mDNS_Execute" model (see "Implementer Notes.txt") + +Revision 1.54 2003/02/20 06:48:35 cheshire +Bug #: 3169535 Xserve RAID needs to do interface-specific registrations +Reviewed by: Josh Graessley, Bob Bradley + +Revision 1.53 2003/01/29 02:21:23 cheshire +Return mStatus_Invalid if can't send packet because socket not available + +Revision 1.52 2003/01/28 19:39:43 jgraessl +Enabling AAAA over IPv4 support. + +Revision 1.51 2003/01/28 05:11:23 cheshire +Fixed backwards comparison in SearchForInterfaceByName + +Revision 1.50 2003/01/13 23:49:44 jgraessl +Merged changes for the following fixes in to top of tree: +3086540 computer name changes not handled properly +3124348 service name changes are not properly handled +3124352 announcements sent in pairs, failing chattiness test + +Revision 1.49 2002/12/23 22:13:30 jgraessl +Reviewed by: Stuart Cheshire +Initial IPv6 support for mDNSResponder. + +Revision 1.48 2002/11/22 01:37:52 cheshire +Bug #: 3108426 mDNSResponder is monitoring ServiceEntities instead of InterfaceEntities + +Revision 1.47 2002/09/21 20:44:51 zarzycki +Added APSL info + +Revision 1.46 2002/09/19 21:25:35 cheshire +mDNS_snprintf() doesn't need to be in a separate file + +Revision 1.45 2002/09/17 01:45:13 cheshire +Add LIST_ALL_INTERFACES symbol for debugging + +Revision 1.44 2002/09/17 01:36:23 cheshire +Move Puma support to CFSocketPuma.c + +Revision 1.43 2002/09/17 01:05:28 cheshire +Change mDNS_AdvertiseLocalAddresses to be an Init parameter instead of a global + +Revision 1.42 2002/09/16 23:13:50 cheshire +Minor code tidying + + */ + +// *************************************************************************** +// mDNS-CFSocket.c: +// Supporting routines to run mDNS on a CFRunLoop platform +// *************************************************************************** + +// Open Transport 2.7.x on Mac OS 9 used to send Multicast DNS queries to UDP port 53, +// before the Multicast DNS port was changed to 5353. For this reason, the mDNSResponder +// in earlier versions of Mac OS X 10.2 Jaguar used to set mDNS_AllowPort53 to 1 to allow +// it to also listen and answer queries on UDP port 53. Now that Transport 2.8 (included in +// the Classic subsystem of Mac OS X 10.2 Jaguar) has been corrected to issue Multicast DNS +// queries on UDP port 5353, this backwards-compatibility legacy support is no longer needed. +#define mDNS_AllowPort53 0 + +// For debugging, set LIST_ALL_INTERFACES to 1 to display all found interfaces, +// including ones that mDNSResponder chooses not to use. +#define LIST_ALL_INTERFACES 0 + +// For enabling AAAA records over IPv4. Setting this to 0 sends only +// A records over IPv4 and AAAA over IPv6. Setting this to 1 sends both +// AAAA and A records over both IPv4 and IPv6. +#define AAAA_OVER_V4 1 + +#include "mDNSClientAPI.h" // Defines the interface provided to the client layer above +#include "mDNSPlatformFunctions.h" // Defines the interface to the supporting layer below +#include "mDNSMacOSX.h" // Defines the specific types needed to run mDNS on this platform + +#include +#include // For select() and close() +#include // For va_list support +#include +#include +#include +#include +#include +#include +#include +#include + +#include // For IP_RECVTTL +#ifndef IP_RECVTTL +#define IP_RECVTTL 24 /* bool; receive reception TTL w/dgram */ +#endif + +#include // For n_long, required by below +#include // For IPTOS_LOWDELAY etc. +#include // For IN6_IFF_NOTREADY etc. + +// Code contributed by Dave Heller: +// Define RUN_ON_PUMA_WITHOUT_IFADDRS to compile code that will +// work on Mac OS X 10.1, which does not have the getifaddrs call. +#define RUN_ON_PUMA_WITHOUT_IFADDRS 0 +#if RUN_ON_PUMA_WITHOUT_IFADDRS +#include "CFSocketPuma.c" +#else +#include +#endif + +#include +#include +#include + +// *************************************************************************** +// Globals + +static mDNSu32 clockdivisor = 0; + +// *************************************************************************** +// Macros + +#define mDNSSameIPv4Address(A,B) ((A).NotAnInteger == (B).NotAnInteger) +#define mDNSSameIPv6Address(A,B) ((A).l[0] == (B).l[0] && (A).l[1] == (B).l[1] && (A).l[2] == (B).l[2] && (A).l[3] == (B).l[3]) + +#define mDNSAddressIsAllDNSLinkGroup(X) ( \ + ((X)->type == mDNSAddrType_IPv4 && mDNSSameIPv4Address((X)->ip.v4, AllDNSLinkGroup )) || \ + ((X)->type == mDNSAddrType_IPv6 && mDNSSameIPv6Address((X)->ip.v6, AllDNSLinkGroupv6)) ) + +// *************************************************************************** +// Functions + +// Note, this uses mDNS_vsnprintf instead of standard "vsnprintf", because mDNS_vsnprintf knows +// how to print special data types like IP addresses and length-prefixed domain names +#if MDNS_DEBUGMSGS +mDNSexport void debugf_(const char *format, ...) + { + unsigned char buffer[512]; + va_list ptr; + va_start(ptr,format); + buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0; + va_end(ptr); + fprintf(stderr,"%s\n", buffer); + fflush(stderr); + } +#endif + +#if MDNS_DEBUGMSGS > 1 +mDNSexport void verbosedebugf_(const char *format, ...) + { + unsigned char buffer[512]; + va_list ptr; + va_start(ptr,format); + buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0; + va_end(ptr); + fprintf(stderr,"%s\n", buffer); + fflush(stderr); + } +#endif + +mDNSexport void LogMsg(const char *format, ...) + { + unsigned char buffer[512]; + va_list ptr; + va_start(ptr,format); + buffer[mDNS_vsnprintf((char *)buffer, sizeof(buffer), format, ptr)] = 0; + va_end(ptr); + + extern int debug_mode; + if (debug_mode) // In debug_mode we write to stderr + { + fprintf(stderr,"%s\n", buffer); + fflush(stderr); + } + else // else, in production mode, we write to syslog + { + openlog("mDNSResponder", LOG_CONS | LOG_PERROR | LOG_PID, LOG_DAEMON); + syslog(LOG_ERR, "%s", buffer); + closelog(); + } + } + +mDNSlocal struct ifaddrs* myGetIfAddrs(int refresh) + { + static struct ifaddrs *ifa = NULL; + + if (refresh && ifa) + { + freeifaddrs(ifa); + ifa = NULL; + } + + if (ifa == NULL) getifaddrs(&ifa); + + return ifa; + } + +mDNSlocal int myIfIndexToName(u_short index, char* name) + { + struct ifaddrs *ifa; + for (ifa = myGetIfAddrs(0); ifa; ifa = ifa->ifa_next) + if (ifa->ifa_addr->sa_family == AF_LINK) + if (((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index == index) + { strncpy(name, ifa->ifa_name, IF_NAMESIZE); return 0; } + return -1; + } + +mDNSexport mDNSInterfaceID mDNSPlatformInterfaceIDfromInterfaceIndex(const mDNS *const m, mDNSu32 index) + { + NetworkInterfaceInfoOSX *i; + if (index == (uint32_t)~0) return((mDNSInterfaceID)~0); + if (index) + for (i = m->p->InterfaceList; i; i = i->next) + if (i->ifinfo.InterfaceID && i->scope_id == index) // Don't get tricked by inactive interfaces + return(i->ifinfo.InterfaceID); + return(mDNSNULL); + } + +mDNSexport mDNSu32 mDNSPlatformInterfaceIndexfromInterfaceID(const mDNS *const m, mDNSInterfaceID id) + { + NetworkInterfaceInfoOSX *i; + if (id == (mDNSInterfaceID)~0) return((mDNSu32)~0); + if (id) + for (i = m->p->InterfaceList; i; i = i->next) + // Don't use i->ifinfo.InterfaceID here because we want to find inactive interfaces where that's not set + if ((mDNSInterfaceID)i == id) + return i->scope_id; + return 0; + } + +mDNSexport mStatus mDNSPlatformSendUDP(const mDNS *const m, const DNSMessage *const msg, const mDNSu8 *const end, + mDNSInterfaceID InterfaceID, mDNSIPPort srcPort, const mDNSAddr *dst, mDNSIPPort dstPort) + { + #pragma unused(m) + NetworkInterfaceInfoOSX *info = (NetworkInterfaceInfoOSX *)InterfaceID; + struct sockaddr_storage to; + int s, err; + + if (!InterfaceID) { LogMsg("mDNSPlatformSendUDP ERROR! Cannot send from zero InterfaceID"); return mStatus_BadParamErr; } + + if (dst->type == mDNSAddrType_IPv4) + { + struct sockaddr_in* sin_to = (struct sockaddr_in*)&to; + sin_to->sin_len = sizeof(*sin_to); + sin_to->sin_family = AF_INET; + sin_to->sin_port = dstPort.NotAnInteger; + sin_to->sin_addr.s_addr = dst->ip.v4.NotAnInteger; + } + else if (dst->type == mDNSAddrType_IPv6) + { + struct sockaddr_in6* sin6_to = (struct sockaddr_in6*)&to; + sin6_to->sin6_len = sizeof(*sin6_to); + sin6_to->sin6_family = AF_INET6; + sin6_to->sin6_port = dstPort.NotAnInteger; + sin6_to->sin6_flowinfo = 0; + sin6_to->sin6_addr = *(struct in6_addr*)&dst->ip.v6; + sin6_to->sin6_scope_id = info->scope_id; + } + else + { + LogMsg("mDNSPlatformSendUDP: dst is not an IPv4 or IPv6 address!\n"); + return mStatus_BadParamErr; + } + + if (srcPort.NotAnInteger == MulticastDNSPort.NotAnInteger) + { + if (dst->type == mDNSAddrType_IPv4) s = info->sktv4; + else if (dst->type == mDNSAddrType_IPv6) s = info->sktv6; + else s = -1; + } +#if mDNS_AllowPort53 + else if (srcPort.NotAnInteger == UnicastDNSPort.NotAnInteger && dst->type == mDNSAddrType_IPv4) + s = info->skt53; +#endif + else { LogMsg("Source port %d not allowed", (mDNSu16)srcPort.b[0]<<8 | srcPort.b[1]); return(-1); } + + if (s >= 0) + verbosedebugf("mDNSPlatformSendUDP: sending on InterfaceID %X %s/%d to %#a:%d skt %d", + InterfaceID, info->ifa_name, dst->type, dst, (mDNSu16)dstPort.b[0]<<8 | dstPort.b[1], s); + else + verbosedebugf("mDNSPlatformSendUDP: NOT sending on InterfaceID %X %s/%d (socket of this type not available)", + InterfaceID, info->ifa_name, dst->type, dst, (mDNSu16)dstPort.b[0]<<8 | dstPort.b[1]); + + // Note: When sending, mDNSCore may often ask us to send both a v4 multicast packet and then a v6 multicast packet + // If we don't have the corresponding type of socket available, then return mStatus_Invalid + if (s < 0) return(mStatus_Invalid); + + err = sendto(s, msg, (UInt8*)end - (UInt8*)msg, 0, (struct sockaddr *)&to, to.ss_len); + if (err < 0) + { + // Don't report EHOSTDOWN (i.e. ARP failure) to unicast destinations + if (errno == EHOSTDOWN && !mDNSAddressIsAllDNSLinkGroup(dst)) return(err); + // Don't report EHOSTUNREACH in the first two minutes after boot + // This is because mDNSResponder intentionally starts up early in the boot process (See ) + // but this means that sometimes it starts before configd has finished setting up the multicast routing entries. + if (errno == EHOSTUNREACH && (mDNSu32)(m->timenow) < (mDNSu32)(mDNSPlatformOneSecond * 120)) return(err); + LogMsg("mDNSPlatformSendUDP sendto failed to send packet on InterfaceID %p %s/%ld to %#a:%d skt %d error %d errno %d (%s)", + InterfaceID, info->ifa_name, dst->type, dst, (mDNSu16)dstPort.b[0]<<8 | dstPort.b[1], s, err, errno, strerror(errno)); + return(err); + } + + return(mStatus_NoError); + } + +mDNSlocal ssize_t myrecvfrom(const int s, void *const buffer, const size_t max, + struct sockaddr *const from, size_t *const fromlen, mDNSAddr *dstaddr, char ifname[IF_NAMESIZE], mDNSu8 *ttl) + { + static unsigned int numLogMessages = 0; + struct iovec databuffers = { (char *)buffer, max }; + struct msghdr msg; + ssize_t n; + struct cmsghdr *cmPtr; + char ancillary[1024]; + + *ttl = 255; // If kernel fails to provide TTL data (e.g. Jaguar doesn't) then assume the TTL was 255 as it should be + + // Set up the message + msg.msg_name = (caddr_t)from; + msg.msg_namelen = *fromlen; + msg.msg_iov = &databuffers; + msg.msg_iovlen = 1; + msg.msg_control = (caddr_t)&ancillary; + msg.msg_controllen = sizeof(ancillary); + msg.msg_flags = 0; + + // Receive the data + n = recvmsg(s, &msg, 0); + if (n<0) + { + if (errno != EWOULDBLOCK && numLogMessages++ < 100) LogMsg("CFSocket.c: recvmsg(%d) returned error %d errno %d", s, n, errno); + return(-1); + } + if (msg.msg_controllen < (int)sizeof(struct cmsghdr)) + { + if (numLogMessages++ < 100) LogMsg("CFSocket.c: recvmsg(%d) msg.msg_controllen %d < sizeof(struct cmsghdr) %lu", + s, msg.msg_controllen, sizeof(struct cmsghdr)); + return(-1); + } + if (msg.msg_flags & MSG_CTRUNC) + { + if (numLogMessages++ < 100) LogMsg("CFSocket.c: recvmsg(%d) msg.msg_flags & MSG_CTRUNC", s); + return(-1); + } + + *fromlen = msg.msg_namelen; + + // Parse each option out of the ancillary data. + for (cmPtr = CMSG_FIRSTHDR(&msg); cmPtr; cmPtr = CMSG_NXTHDR(&msg, cmPtr)) + { + // debugf("myrecvfrom cmsg_level %d cmsg_type %d", cmPtr->cmsg_level, cmPtr->cmsg_type); + if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVDSTADDR) + { + dstaddr->type = mDNSAddrType_IPv4; + dstaddr->ip.v4.NotAnInteger = *(u_int32_t*)CMSG_DATA(cmPtr); + } + if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVIF) + { + struct sockaddr_dl *sdl = (struct sockaddr_dl *)CMSG_DATA(cmPtr); + if (sdl->sdl_nlen < IF_NAMESIZE) + { + mDNSPlatformMemCopy(sdl->sdl_data, ifname, sdl->sdl_nlen); + ifname[sdl->sdl_nlen] = 0; + // debugf("IP_RECVIF sdl_index %d, sdl_data %s len %d", sdl->sdl_index, ifname, sdl->sdl_nlen); + } + } + if (cmPtr->cmsg_level == IPPROTO_IP && cmPtr->cmsg_type == IP_RECVTTL) + { + *ttl = *(u_char*)CMSG_DATA(cmPtr); + } + if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_PKTINFO) + { + struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmPtr); + dstaddr->type = mDNSAddrType_IPv6; + dstaddr->ip.v6 = *(mDNSv6Addr*)&ip6_info->ipi6_addr; + myIfIndexToName(ip6_info->ipi6_ifindex, ifname); + } + if (cmPtr->cmsg_level == IPPROTO_IPV6 && cmPtr->cmsg_type == IPV6_HOPLIMIT) + { + *ttl = *(int*)CMSG_DATA(cmPtr); + } + } + + return(n); + } + +mDNSlocal void myCFSocketCallBack(CFSocketRef cfs, CFSocketCallBackType CallBackType, CFDataRef address, const void *data, void *context) + { + mDNSAddr senderAddr, destAddr; + mDNSIPPort senderPort, destPort = MulticastDNSPort; + NetworkInterfaceInfoOSX *info = (NetworkInterfaceInfoOSX *)context; + mDNS *const m = info->m; + DNSMessage packet; + struct sockaddr_storage from; + size_t fromlen = sizeof(from); + char packetifname[IF_NAMESIZE] = ""; + int err, s1 = -1, skt = CFSocketGetNative(cfs); + int count = 0; + + (void)address; // Parameter not used + (void)data; // Parameter not used + + if (CallBackType != kCFSocketReadCallBack) LogMsg("myCFSocketCallBack: Why is CallBackType %d not kCFSocketReadCallBack?", CallBackType); + +#if mDNS_AllowPort53 + if (cfs == info->cfs53) { s1 = info->skt53; destPort = UnicastDNSPort; } + else +#endif + if (cfs == info->cfsv4) s1 = info->sktv4; + else if (cfs == info->cfsv6) s1 = info->sktv6; + + if (s1 < 0 || s1 != skt) + { + LogMsg("myCFSocketCallBack: s1 %d native socket %d, cfs %p", s1, skt, cfs); +#if mDNS_AllowPort53 + LogMsg("myCFSocketCallBack: cfs53 %p, skt53 %d", info->cfs53, info->skt53); +#endif + LogMsg("myCFSocketCallBack: cfsv4 %p, sktv4 %d", info->cfsv4, info->sktv4); + LogMsg("myCFSocketCallBack: cfsv6 %p, sktv6 %d", info->cfsv6, info->sktv6); + } + + mDNSu8 ttl; + while ((err = myrecvfrom(s1, &packet, sizeof(packet), (struct sockaddr *)&from, &fromlen, &destAddr, packetifname, &ttl)) >= 0) + { + count++; + if (from.ss_family == AF_INET) + { + struct sockaddr_in *sin = (struct sockaddr_in*)&from; + senderAddr.type = mDNSAddrType_IPv4; + senderAddr.ip.v4.NotAnInteger = sin->sin_addr.s_addr; + senderPort.NotAnInteger = sin->sin_port; + } + else if (from.ss_family == AF_INET6) + { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&from; + senderAddr.type = mDNSAddrType_IPv6; + senderAddr.ip.v6 = *(mDNSv6Addr*)&sin6->sin6_addr; + senderPort.NotAnInteger = sin6->sin6_port; + } + else + { + LogMsg("myCFSocketCallBack from is unknown address family %d", from.ss_family); + return; + } + + // Even though we indicated a specific interface in the IP_ADD_MEMBERSHIP call, a weirdness of the + // sockets API means that even though this socket has only officially joined the multicast group + // on one specific interface, the kernel will still deliver multicast packets to it no matter which + // interface they arrive on. According to the official Unix Powers That Be, this is Not A Bug. + // To work around this weirdness, we use the IP_RECVIF option to find the name of the interface + // on which the packet arrived, and ignore the packet if it really arrived on some other interface. + if (strcmp(info->ifa_name, packetifname)) + { + verbosedebugf("myCFSocketCallBack got a packet from %#a to %#a on interface %#a/%s (Ignored -- really arrived on interface %s)", + &senderAddr, &destAddr, &info->ifinfo.ip, info->ifa_name, packetifname); + return; + } + else + verbosedebugf("myCFSocketCallBack got a packet from %#a to %#a on interface %#a/%s", + &senderAddr, &destAddr, &info->ifinfo.ip, info->ifa_name); + + if (err < (int)sizeof(DNSMessageHeader)) { debugf("myCFSocketCallBack packet length (%d) too short", err); return; } + + mDNSCoreReceive(m, &packet, (unsigned char*)&packet + err, &senderAddr, senderPort, &destAddr, destPort, info->ifinfo.InterfaceID, ttl); + } + + if (err < 0 && (errno != EWOULDBLOCK || count == 0)) + { + // Something is busted here. + // CFSocket says there is a packet, but myrecvfrom says there is not. + // Try calling select() to get another opinion. + // Find out about other socket parameter that can help understand why select() says the socket is ready for read + // All of this is racy, as data may have arrived after the call to select() + int save_errno = errno; + int so_error = -1; + int so_nread = -1; + int fionread = -1; + int solen = sizeof(int); + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(s1, &readfds); + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + int selectresult = select(s1+1, &readfds, NULL, NULL, &timeout); + if (getsockopt(s1, SOL_SOCKET, SO_ERROR, &so_error, &solen) == -1) + LogMsg("myCFSocketCallBack getsockopt(SO_ERROR) error %d", errno); + if (getsockopt(s1, SOL_SOCKET, SO_NREAD, &so_nread, &solen) == -1) + LogMsg("myCFSocketCallBack getsockopt(SO_NREAD) error %d", errno); + if (ioctl(s1, FIONREAD, &fionread) == -1) + LogMsg("myCFSocketCallBack ioctl(FIONREAD) error %d", errno); + static unsigned int numLogMessages = 0; + if (numLogMessages++ < 100) + LogMsg("myCFSocketCallBack recvfrom skt %d error %d errno %d (%s) select %d (%spackets waiting) so_error %d so_nread %d fionread %d count %d", + s1, err, save_errno, strerror(save_errno), selectresult, FD_ISSET(s1, &readfds) ? "" : "*NO* ", so_error, so_nread, fionread, count); + sleep(1); // After logging this error, rate limit so we don't flood syslog + } + } + +// This gets the text of the field currently labelled "Computer Name" in the Sharing Prefs Control Panel +mDNSlocal void GetUserSpecifiedFriendlyComputerName(domainlabel *const namelabel) + { + CFStringEncoding encoding = kCFStringEncodingUTF8; + CFStringRef cfs = SCDynamicStoreCopyComputerName(NULL, &encoding); + if (cfs) + { + CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8); + CFRelease(cfs); + } + } + +// This gets the text of the field currently labelled "Rendezvous Name" in the Sharing Prefs Control Panel +mDNSlocal void GetUserSpecifiedRFC1034ComputerName(domainlabel *const namelabel) + { + CFStringRef cfs = SCDynamicStoreCopyLocalHostName(NULL); + if (cfs) + { + CFStringGetPascalString(cfs, namelabel->c, sizeof(*namelabel), kCFStringEncodingUTF8); + CFRelease(cfs); + } + } + +mDNSlocal mStatus SetupSocket(NetworkInterfaceInfoOSX *i, mDNSIPPort port, int *s, CFSocketRef *c) + { + const int on = 1; + const int twofivefive = 255; + + if (*s >= 0) { LogMsg("SetupSocket ERROR: socket %d is already set", *s); return(-1); } + if (*c) { LogMsg("SetupSocket ERROR: CFSocketRef %p is already set", *c); return(-1); } + + // Open the socket... + int skt = socket(i->sa_family, SOCK_DGRAM, IPPROTO_UDP); + if (skt < 0) { LogMsg("socket error %d errno %d (%s)", skt, errno, strerror(errno)); return(skt); } + + // ... with a shared UDP port + mStatus err = setsockopt(skt, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)); + if (err < 0) { LogMsg("setsockopt - SO_REUSEPORT error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + if (i->sa_family == AF_INET) + { + // We want to receive destination addresses + err = setsockopt(skt, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on)); + if (err < 0) { LogMsg("setsockopt - IP_RECVDSTADDR error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // We want to receive interface identifiers + err = setsockopt(skt, IPPROTO_IP, IP_RECVIF, &on, sizeof(on)); + if (err < 0) { LogMsg("setsockopt - IP_RECVIF error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // We want to receive packet TTL value so we can check it + err = setsockopt(skt, IPPROTO_IP, IP_RECVTTL, &on, sizeof(on)); + // We ignore errors here -- we already know Jaguar doesn't support this, but we can get by without it + + // Add multicast group membership on this interface + struct in_addr addr = { i->ifinfo.ip.ip.v4.NotAnInteger }; + struct ip_mreq imr; + imr.imr_multiaddr.s_addr = AllDNSLinkGroup.NotAnInteger; + imr.imr_interface = addr; + err = setsockopt(skt, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof(imr)); + if (err < 0) { LogMsg("setsockopt - IP_ADD_MEMBERSHIP error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // Specify outgoing interface too + err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr)); + if (err < 0) { LogMsg("setsockopt - IP_MULTICAST_IF error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // Send unicast packets with TTL 255 + err = setsockopt(skt, IPPROTO_IP, IP_TTL, &twofivefive, sizeof(twofivefive)); + if (err < 0) { LogMsg("setsockopt - IP_TTL error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // And multicast packets with TTL 255 too + err = setsockopt(skt, IPPROTO_IP, IP_MULTICAST_TTL, &twofivefive, sizeof(twofivefive)); + if (err < 0) { LogMsg("setsockopt - IP_MULTICAST_TTL error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate + const int ip_tosbits = IPTOS_LOWDELAY | IPTOS_THROUGHPUT; + err = setsockopt(skt, IPPROTO_IP, IP_TOS, &ip_tosbits, sizeof(ip_tosbits)); + if (err < 0) { LogMsg("setsockopt - IP_TOS error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // And start listening for packets + struct sockaddr_in listening_sockaddr; + listening_sockaddr.sin_family = AF_INET; + listening_sockaddr.sin_port = port.NotAnInteger; + listening_sockaddr.sin_addr.s_addr = 0; // Want to receive multicasts AND unicasts on this socket + err = bind(skt, (struct sockaddr *) &listening_sockaddr, sizeof(listening_sockaddr)); + if (err) + { + // If we fail to bind to port 53 (because we're not root), that's okay, just tidy up and silently continue + if (port.NotAnInteger == UnicastDNSPort.NotAnInteger) { close(skt); err = 0; } + else LogMsg("bind error %ld errno %d (%s)", err, errno, strerror(errno)); + return(err); + } + } + else if (i->sa_family == AF_INET6) + { + // We want to receive destination addresses and receive interface identifiers + err = setsockopt(skt, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on)); + if (err < 0) { LogMsg("setsockopt - IPV6_PKTINFO error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // We want to receive packet hop count value so we can check it + err = setsockopt(skt, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on)); + if (err < 0) { LogMsg("setsockopt - IPV6_HOPLIMIT error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // We want to receive only IPv6 packets, without this option, we may + // get IPv4 addresses as mapped addresses. + err = setsockopt(skt, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); + if (err < 0) { LogMsg("setsockopt - IPV6_V6ONLY error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // Add multicast group membership on this interface + int interface_id = if_nametoindex(i->ifa_name); + struct ipv6_mreq i6mr; + i6mr.ipv6mr_interface = interface_id; + i6mr.ipv6mr_multiaddr = *(struct in6_addr*)&AllDNSLinkGroupv6; + err = setsockopt(skt, IPPROTO_IPV6, IPV6_JOIN_GROUP, &i6mr, sizeof(i6mr)); + if (err < 0) { LogMsg("setsockopt - IPV6_JOIN_GROUP error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // Specify outgoing interface too + err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_IF, &interface_id, sizeof(interface_id)); + if (err < 0) { LogMsg("setsockopt - IPV6_MULTICAST_IF error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // Send unicast packets with TTL 255 + err = setsockopt(skt, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &twofivefive, sizeof(twofivefive)); + if (err < 0) { LogMsg("setsockopt - IPV6_UNICAST_HOPS error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // And multicast packets with TTL 255 too + err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &twofivefive, sizeof(twofivefive)); + if (err < 0) { LogMsg("setsockopt - IPV6_MULTICAST_HOPS error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // Note: IPV6_TCLASS appears not to be implemented on OS X right now (or indeed on ANY version of Unix?) + #ifdef IPV6_TCLASS + // Mark packets as high-throughput/low-delay (i.e. lowest reliability) to get maximum 802.11 multicast rate + int tclass = IPTOS_LOWDELAY | IPTOS_THROUGHPUT; // This may not be right (since tclass is not implemented on OS X, I can't test it) + err = setsockopt(skt, IPPROTO_IPV6, IPV6_TCLASS, &tclass, sizeof(tclass)); + if (err < 0) { LogMsg("setsockopt - IPV6_TCLASS error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + #endif + + // Want to receive our own packets + err = setsockopt(skt, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &on, sizeof(on)); + if (err < 0) { LogMsg("setsockopt - IPV6_MULTICAST_LOOP error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + + // And start listening for packets + struct sockaddr_in6 listening_sockaddr6; + bzero(&listening_sockaddr6, sizeof(listening_sockaddr6)); + listening_sockaddr6.sin6_len = sizeof(listening_sockaddr6); + listening_sockaddr6.sin6_family = AF_INET6; + listening_sockaddr6.sin6_port = port.NotAnInteger; + listening_sockaddr6.sin6_flowinfo = 0; +// listening_sockaddr6.sin6_addr = IN6ADDR_ANY_INIT; // Want to receive multicasts AND unicasts on this socket + listening_sockaddr6.sin6_scope_id = 0; + err = bind(skt, (struct sockaddr *) &listening_sockaddr6, sizeof(listening_sockaddr6)); + if (err) { LogMsg("bind error %ld errno %d (%s)", err, errno, strerror(errno)); return(err); } + } + + fcntl(skt, F_SETFL, fcntl(skt, F_GETFL, 0) | O_NONBLOCK); // set non-blocking + *s = skt; + CFSocketContext myCFSocketContext = { 0, i->ifinfo.InterfaceID, NULL, NULL, NULL }; + *c = CFSocketCreateWithNative(kCFAllocatorDefault, *s, kCFSocketReadCallBack, myCFSocketCallBack, &myCFSocketContext); + CFRunLoopSourceRef rls = CFSocketCreateRunLoopSource(kCFAllocatorDefault, *c, 0); + CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); + CFRelease(rls); + + return(err); + } + +mDNSlocal mStatus SetupAddr(mDNSAddr *ip, const struct sockaddr *const sa) + { + if (sa->sa_family == AF_INET) + { + struct sockaddr_in *ifa_addr = (struct sockaddr_in *)sa; + ip->type = mDNSAddrType_IPv4; + ip->ip.v4.NotAnInteger = ifa_addr->sin_addr.s_addr; + return(0); + } + else if (sa->sa_family == AF_INET6) + { + struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6 *)sa; + ip->type = mDNSAddrType_IPv6; + if (IN6_IS_ADDR_LINKLOCAL(&ifa_addr->sin6_addr)) ifa_addr->sin6_addr.__u6_addr.__u6_addr16[1] = 0; + ip->ip.v6 = *(mDNSv6Addr*)&ifa_addr->sin6_addr; + return(0); + } + else + { + LogMsg("SetupAddr invalid sa_family %d", sa->sa_family); + return(-1); + } + } + +mDNSlocal mStatus AddInterfaceToList(mDNS *const m, struct ifaddrs *ifa) + { + mDNSu32 scope_id = if_nametoindex(ifa->ifa_name); + mDNSAddr ip; + SetupAddr(&ip, ifa->ifa_addr); + NetworkInterfaceInfoOSX **p; + for (p = &m->p->InterfaceList; *p; p = &(*p)->next) + if (scope_id == (*p)->scope_id && mDNSSameAddress(&ip, &(*p)->ifinfo.ip)) + { + debugf("AddInterfaceToList: Found existing interface %u with address %#a", scope_id, &ip); + (*p)->CurrentlyActive = mDNStrue; + return(0); + } + + debugf("AddInterfaceToList: Making new interface %u with address %#a", scope_id, &ip); + NetworkInterfaceInfoOSX *i = (NetworkInterfaceInfoOSX *)mallocL("NetworkInterfaceInfoOSX", sizeof(*i)); + if (!i) return(-1); + i->ifa_name = (char *)mallocL("NetworkInterfaceInfoOSX name", strlen(ifa->ifa_name) + 1); + if (!i->ifa_name) { freeL("NetworkInterfaceInfoOSX", i); return(-1); } + strcpy(i->ifa_name, ifa->ifa_name); + + i->ifinfo.InterfaceID = mDNSNULL; + i->ifinfo.ip = ip; + i->ifinfo.Advertise = m->AdvertiseLocalAddresses; + i->ifinfo.TxAndRx = mDNSfalse; // For now; will be set up later at the end of UpdateInterfaceList + + i->next = mDNSNULL; + i->m = m; + i->scope_id = scope_id; + i->CurrentlyActive = mDNStrue; + i->sa_family = ifa->ifa_addr->sa_family; + #if mDNS_AllowPort53 + i->skt53 = -1; + i->cfs53 = NULL; + #endif + i->sktv4 = -1; + i->cfsv4 = NULL; + i->sktv6 = -1; + i->cfsv6 = NULL; + + if (!i->ifa_name) return(-1); + *p = i; + return(0); + } + +mDNSlocal NetworkInterfaceInfoOSX *FindRoutableIPv4(mDNS *const m, mDNSu32 scope_id) + { + NetworkInterfaceInfoOSX *i; + for (i = m->p->InterfaceList; i; i = i->next) + if (i->CurrentlyActive && i->scope_id == scope_id && i->ifinfo.ip.type == mDNSAddrType_IPv4) + if (!(i->ifinfo.ip.ip.v4.b[0] == 169 && i->ifinfo.ip.ip.v4.b[1] == 254)) + return(i); + return(mDNSNULL); + } + +mDNSlocal mStatus UpdateInterfaceList(mDNS *const m) + { + mDNSBool foundav4 = mDNSfalse; + struct ifaddrs *ifa = myGetIfAddrs(1); + struct ifaddrs *theLoopback = NULL; + int err = (ifa != NULL) ? 0 : (errno != 0 ? errno : -1); + int InfoSocket = err ? -1 : socket(AF_INET6, SOCK_DGRAM, 0); + if (err) return(err); + + // Set up the nice label + m->nicelabel.c[0] = 0; + GetUserSpecifiedFriendlyComputerName(&m->nicelabel); + if (m->nicelabel.c[0] == 0) MakeDomainLabelFromLiteralString(&m->nicelabel, "Macintosh"); + + // Set up the RFC 1034-compliant label + domainlabel hostlabel; + hostlabel.c[0] = 0; + GetUserSpecifiedRFC1034ComputerName(&hostlabel); + if (hostlabel.c[0] == 0) MakeDomainLabelFromLiteralString(&hostlabel, "Macintosh"); + // If the user has changed their dot-local host name since the last time we checked, then update our local copy. + // If the user has not changed their dot-local host name, then leave ours alone (m->hostlabel may have gone through + // repeated conflict resolution to get to its current value, and if we reset it, we'll have to go through all that again.) + if (SameDomainLabel(m->p->userhostlabel.c, hostlabel.c)) + debugf("Userhostlabel (%#s) unchanged since last time; not changing m->hostlabel (%#s)", m->p->userhostlabel.c, m->hostlabel.c); + else + { + debugf("Updating m->hostlabel to %#s", hostlabel.c); + m->p->userhostlabel = m->hostlabel = hostlabel; + mDNS_GenerateFQDN(m); + } + + while (ifa) + { +#if LIST_ALL_INTERFACES + if (ifa->ifa_addr->sa_family == AF_APPLETALK) + debugf("UpdateInterfaceList: %4s(%d) Flags %04X Family %2d is AF_APPLETALK", + ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family); + else if (ifa->ifa_addr->sa_family == AF_LINK) + debugf("UpdateInterfaceList: %4s(%d) Flags %04X Family %2d is AF_LINK", + ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family); + else if (ifa->ifa_addr->sa_family != AF_INET && ifa->ifa_addr->sa_family != AF_INET6) + debugf("UpdateInterfaceList: %4s(%d) Flags %04X Family %2d not AF_INET (2) or AF_INET6 (30)", + ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family); + if (!(ifa->ifa_flags & IFF_UP)) + debugf("UpdateInterfaceList: %4s(%d) Flags %04X Family %2d Interface not IFF_UP", + ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family); + if (ifa->ifa_flags & IFF_POINTOPOINT) + debugf("UpdateInterfaceList: %4s(%d) Flags %04X Family %2d Interface IFF_POINTOPOINT", + ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family); + if (ifa->ifa_flags & IFF_LOOPBACK) + debugf("UpdateInterfaceList: %4s(%d) Flags %04X Family %2d Interface IFF_LOOPBACK", + ifa->ifa_name, if_nametoindex(ifa->ifa_name), ifa->ifa_flags, ifa->ifa_addr->sa_family); +#endif + if ((ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) && + (ifa->ifa_flags & IFF_MULTICAST) && + (ifa->ifa_flags & IFF_UP) && !(ifa->ifa_flags & IFF_POINTOPOINT)) + { + int ifru_flags6 = 0; + if (ifa->ifa_addr->sa_family == AF_INET6 && InfoSocket >= 0) + { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; + struct in6_ifreq ifr6; + bzero((char *)&ifr6, sizeof(ifr6)); + strncpy(ifr6.ifr_name, ifa->ifa_name, sizeof(ifr6.ifr_name)); + ifr6.ifr_addr = *sin6; + if (ioctl(InfoSocket, SIOCGIFAFLAG_IN6, &ifr6) != -1) + ifru_flags6 = ifr6.ifr_ifru.ifru_flags6; + verbosedebugf("%s %.16a %04X %04X", ifa->ifa_name, &sin6->sin6_addr, ifa->ifa_flags, ifru_flags6); + } + if (!(ifru_flags6 & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED | IN6_IFF_DEPRECATED | IN6_IFF_TEMPORARY))) + { + if (ifa->ifa_flags & IFF_LOOPBACK) + theLoopback = ifa; + else + { + AddInterfaceToList(m, ifa); + if (ifa->ifa_addr->sa_family == AF_INET) + foundav4 = mDNStrue; + } + } + } + ifa = ifa->ifa_next; + } + +// Temporary workaround: Multicast loopback on IPv6 interfaces appears not to work. +// In the interim, we skip loopback interface only if we found at least one v4 interface to use + if (!foundav4 && theLoopback) + AddInterfaceToList(m, theLoopback); + + // Now the list is complete, set the TxAndRx setting for each interface. + // We always send and receive using IPv4. + // To reduce traffic, we send and receive using IPv6 only on interfaces that have no routable IPv4 address. + // Having a routable IPv4 address assigned is a reasonable indicator of being on a large configured network, + // which means there's a good chance that most or all the other devices on that network should also have v4. + // By doing this we lose the ability to talk to true v6-only devices on that link, but we cut the packet rate in half. + // At this time, reducing the packet rate is more important than v6-only devices on a large configured network, + // so we are willing to make that sacrifice. + NetworkInterfaceInfoOSX *i; + for (i = m->p->InterfaceList; i; i = i->next) + if (i->CurrentlyActive) + { + mDNSBool txrx = ((i->ifinfo.ip.type == mDNSAddrType_IPv4) || !FindRoutableIPv4(m, i->scope_id)); + if (i->ifinfo.TxAndRx != txrx) + { + i->ifinfo.TxAndRx = txrx; + i->CurrentlyActive = 2; // State change; need to deregister and reregister this interface + } + } + + if (InfoSocket >= 0) close(InfoSocket); + return(err); + } + +mDNSlocal NetworkInterfaceInfoOSX *SearchForInterfaceByName(mDNS *const m, char *ifname, int type) + { + NetworkInterfaceInfoOSX *i; + for (i = m->p->InterfaceList; i; i = i->next) + if (!strcmp(i->ifa_name, ifname) && + i->CurrentlyActive && + ((AAAA_OVER_V4 ) || + (type == AF_INET && i->ifinfo.ip.type == mDNSAddrType_IPv4) || + (type == AF_INET6 && i->ifinfo.ip.type == mDNSAddrType_IPv6) )) return(i); + return(NULL); + } + +mDNSlocal void SetupActiveInterfaces(mDNS *const m) + { + NetworkInterfaceInfoOSX *i; + for (i = m->p->InterfaceList; i; i = i->next) + if (i->CurrentlyActive) + { + mStatus err = 0; + NetworkInterfaceInfo *n = &i->ifinfo; + NetworkInterfaceInfoOSX *alias = SearchForInterfaceByName(m, i->ifa_name, i->sa_family); + if (!alias) alias = i; + + if (n->InterfaceID && n->InterfaceID != (mDNSInterfaceID)alias) + { + LogMsg("SetupActiveInterfaces ERROR! n->InterfaceID %p != alias %p", n->InterfaceID, alias); + n->InterfaceID = mDNSNULL; + } + + if (!n->InterfaceID) + { + n->InterfaceID = (mDNSInterfaceID)alias; + mDNS_RegisterInterface(m, n); + debugf("SetupActiveInterfaces: Registered %s(%lu) InterfaceID %p %#a%s", + i->ifa_name, i->scope_id, alias, &n->ip, n->InterfaceActive ? " (Primary)" : ""); + } + + if (!n->TxAndRx) + debugf("SetupActiveInterfaces: No TX/Rx on %s(%lu) InterfaceID %p %#a", i->ifa_name, i->scope_id, alias, &n->ip); + else + { + if (i->sa_family == AF_INET && alias->sktv4 == -1) + { + #if mDNS_AllowPort53 + err = SetupSocket(i, UnicastDNSPort, &alias->skt53, &alias->cfs53); + #endif + if (!err) err = SetupSocket(i, MulticastDNSPort, &alias->sktv4, &alias->cfsv4); + if (err == 0) debugf("SetupActiveInterfaces: v4 socket%2d %s(%lu) InterfaceID %p %#a", alias->sktv4, i->ifa_name, i->scope_id, n->InterfaceID, &n->ip); + else LogMsg("SetupActiveInterfaces: v4 socket%2d %s(%lu) InterfaceID %p %#a FAILED", alias->sktv4, i->ifa_name, i->scope_id, n->InterfaceID, &n->ip); + } + + if (i->sa_family == AF_INET6 && alias->sktv6 == -1) + { + err = SetupSocket(i, MulticastDNSPort, &alias->sktv6, &alias->cfsv6); + if (err == 0) debugf("SetupActiveInterfaces: v6 socket%2d %s(%lu) InterfaceID %p %#a", alias->sktv6, i->ifa_name, i->scope_id, n->InterfaceID, &n->ip); + else LogMsg("SetupActiveInterfaces: v6 socket%2d %s(%lu) InterfaceID %p %#a FAILED", alias->sktv6, i->ifa_name, i->scope_id, n->InterfaceID, &n->ip); + } + } + } + } + +mDNSlocal void MarkAllInterfacesInactive(mDNS *const m) + { + NetworkInterfaceInfoOSX *i; + for (i = m->p->InterfaceList; i; i = i->next) + i->CurrentlyActive = mDNSfalse; + } + +mDNSlocal mDNSu32 NumCacheRecordsForInterfaceID(mDNS *const m, mDNSInterfaceID id) + { + mDNSu32 slot, used = 0; + CacheRecord *rr; + for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) + for (rr = m->rrcache_hash[slot]; rr; rr=rr->next) + if (rr->resrec.InterfaceID == id) used++; + return(used); + } + +mDNSlocal void ClearInactiveInterfaces(mDNS *const m) + { + // First pass: + // If an interface is going away, then deregister this from the mDNSCore. + // We also have to deregister it if the alias interface that it's using for its InterfaceID is going away. + // We have to do this because mDNSCore will use that InterfaceID when sending packets, and if the memory + // it refers to has gone away we'll crash. + // Don't actually close the sockets or free the memory yet: When the last representative of an interface goes away + // mDNSCore may want to send goodbye packets on that interface. (Not yet implemented, but a good idea anyway.) + NetworkInterfaceInfoOSX *i; + for (i = m->p->InterfaceList; i; i = i->next) + { + // 1. If this interface is no longer active, or its InterfaceID is changing, deregister it + NetworkInterfaceInfoOSX *alias = (NetworkInterfaceInfoOSX *)(i->ifinfo.InterfaceID); + NetworkInterfaceInfoOSX *newalias = SearchForInterfaceByName(m, i->ifa_name, i->sa_family); + if (!newalias) newalias = i; + if (i->ifinfo.InterfaceID && (!i->CurrentlyActive || (alias && !alias->CurrentlyActive) || i->CurrentlyActive == 2 || newalias != alias)) + { + debugf("ClearInactiveInterfaces: Deregistering %#a", &i->ifinfo.ip); + mDNS_DeregisterInterface(m, &i->ifinfo); + i->ifinfo.InterfaceID = mDNSNULL; + } + } + + // Second pass: + // Now that everything that's going to deregister has done so, we can close sockets and free the memory + NetworkInterfaceInfoOSX **p = &m->p->InterfaceList; + while (*p) + { + i = *p; + // 2. Close all our CFSockets. We'll recreate them later as necessary. + // (We may have previously had both v4 and v6, and we may not need both any more.) + // Note: MUST NOT close the underlying native BSD sockets. + // CFSocketInvalidate() will do that for us, in its own good time, which may not necessarily be immediately, + // because it first has to unhook the sockets from its select() call, before it can safely close them. + #if mDNS_AllowPort53 + if (i->cfs53) { CFSocketInvalidate(i->cfs53); CFRelease(i->cfs53); } + i->skt53 = -1; + i->cfs53 = NULL; + #endif + if (i->cfsv4) { CFSocketInvalidate(i->cfsv4); CFRelease(i->cfsv4); } + if (i->cfsv6) { CFSocketInvalidate(i->cfsv6); CFRelease(i->cfsv6); } + i->sktv4 = i->sktv6 = -1; + i->cfsv4 = i->cfsv6 = NULL; + + // 3. If no longer active, delete interface from list and free memory + if (!i->CurrentlyActive && NumCacheRecordsForInterfaceID(m, (mDNSInterfaceID)i) == 0) + { + debugf("ClearInactiveInterfaces: Deleting %#a", &i->ifinfo.ip); + *p = i->next; + if (i->ifa_name) freeL("NetworkInterfaceInfoOSX name", i->ifa_name); + freeL("NetworkInterfaceInfoOSX", i); + } + else + p = &i->next; + } + } + +mDNSlocal void NetworkChanged(SCDynamicStoreRef store, CFArrayRef changedKeys, void *context) + { + (void)store; // Parameter not used + (void)changedKeys; // Parameter not used + debugf("*** Network Configuration Change ***"); + + mDNS *const m = (mDNS *const)context; + MarkAllInterfacesInactive(m); + UpdateInterfaceList(m); + ClearInactiveInterfaces(m); + SetupActiveInterfaces(m); + + if (m->MainCallback) + m->MainCallback(m, mStatus_ConfigChanged); + } + +mDNSlocal mStatus WatchForNetworkChanges(mDNS *const m) + { + mStatus err = -1; + SCDynamicStoreContext context = { 0, m, NULL, NULL, NULL }; + SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("mDNSResponder"), NetworkChanged, &context); + CFStringRef key1 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4); + CFStringRef key2 = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6); + CFStringRef key3 = SCDynamicStoreKeyCreateComputerName(NULL); + CFStringRef key4 = SCDynamicStoreKeyCreateHostNames(NULL); + CFStringRef pattern1 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4); + CFStringRef pattern2 = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6); + + CFMutableArrayRef keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFMutableArrayRef patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + + if (!store) { LogMsg("SCDynamicStoreCreate failed: %s\n", SCErrorString(SCError())); goto error; } + if (!key1 || !key2 || !key3 || !key4 || !keys || !pattern1 || !pattern2 || !patterns) goto error; + + CFArrayAppendValue(keys, key1); + CFArrayAppendValue(keys, key2); + CFArrayAppendValue(keys, key3); + CFArrayAppendValue(keys, key4); + CFArrayAppendValue(patterns, pattern1); + CFArrayAppendValue(patterns, pattern2); + if (!SCDynamicStoreSetNotificationKeys(store, keys, patterns)) + { LogMsg("SCDynamicStoreSetNotificationKeys failed: %s\n", SCErrorString(SCError())); goto error; } + + m->p->StoreRLS = SCDynamicStoreCreateRunLoopSource(NULL, store, 0); + if (!m->p->StoreRLS) { LogMsg("SCDynamicStoreCreateRunLoopSource failed: %s\n", SCErrorString(SCError())); goto error; } + + CFRunLoopAddSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode); + m->p->Store = store; + err = 0; + goto exit; + +error: + if (store) CFRelease(store); + +exit: + if (key1) CFRelease(key1); + if (key2) CFRelease(key2); + if (key3) CFRelease(key3); + if (key4) CFRelease(key4); + if (pattern1) CFRelease(pattern1); + if (pattern2) CFRelease(pattern2); + if (keys) CFRelease(keys); + if (patterns) CFRelease(patterns); + + return(err); + } + +mDNSlocal void PowerChanged(void *refcon, io_service_t service, natural_t messageType, void *messageArgument) + { + mDNS *const m = (mDNS *const)refcon; + (void)service; // Parameter not used + switch(messageType) + { + case kIOMessageCanSystemPowerOff: debugf("PowerChanged kIOMessageCanSystemPowerOff (no action)"); break; // E0000240 + case kIOMessageSystemWillPowerOff: debugf("PowerChanged kIOMessageSystemWillPowerOff"); mDNSCoreMachineSleep(m, true); break; // E0000250 + case kIOMessageSystemWillNotPowerOff: debugf("PowerChanged kIOMessageSystemWillNotPowerOff (no action)"); break; // E0000260 + case kIOMessageCanSystemSleep: debugf("PowerChanged kIOMessageCanSystemSleep (no action)"); break; // E0000270 + case kIOMessageSystemWillSleep: debugf("PowerChanged kIOMessageSystemWillSleep"); mDNSCoreMachineSleep(m, true); break; // E0000280 + case kIOMessageSystemWillNotSleep: debugf("PowerChanged kIOMessageSystemWillNotSleep (no action)"); break; // E0000290 + case kIOMessageSystemHasPoweredOn: debugf("PowerChanged kIOMessageSystemHasPoweredOn"); mDNSCoreMachineSleep(m, false); break; // E0000300 + default: debugf("PowerChanged unknown message %X", messageType); break; + } + IOAllowPowerChange(m->p->PowerConnection, (long)messageArgument); + } + +mDNSlocal mStatus WatchForPowerChanges(mDNS *const m) + { + IONotificationPortRef thePortRef; + m->p->PowerConnection = IORegisterForSystemPower(m, &thePortRef, PowerChanged, &m->p->PowerNotifier); + if (m->p->PowerConnection) + { + m->p->PowerRLS = IONotificationPortGetRunLoopSource(thePortRef); + CFRunLoopAddSource(CFRunLoopGetCurrent(), m->p->PowerRLS, kCFRunLoopDefaultMode); + return(mStatus_NoError); + } + return(-1); + } + +CF_EXPORT CFDictionaryRef _CFCopySystemVersionDictionary(void); +CF_EXPORT const CFStringRef _kCFSystemVersionProductNameKey; +CF_EXPORT const CFStringRef _kCFSystemVersionProductVersionKey; +CF_EXPORT const CFStringRef _kCFSystemVersionBuildVersionKey; + +mDNSexport mDNSBool mDNSMacOSXSystemBuildNumber(char *HINFO_SWstring) + { + int major = 0, minor = 0; + char letter = 0, prodname[256]="Mac OS X", prodvers[256]="", buildver[256]="?"; + CFDictionaryRef vers = _CFCopySystemVersionDictionary(); + if (vers) + { + CFStringRef cfprodname = CFDictionaryGetValue(vers, _kCFSystemVersionProductNameKey); + CFStringRef cfprodvers = CFDictionaryGetValue(vers, _kCFSystemVersionProductVersionKey); + CFStringRef cfbuildver = CFDictionaryGetValue(vers, _kCFSystemVersionBuildVersionKey); + if (cfprodname) CFStringGetCString(cfprodname, prodname, sizeof(prodname), kCFStringEncodingUTF8); + if (cfprodvers) CFStringGetCString(cfprodvers, prodvers, sizeof(prodvers), kCFStringEncodingUTF8); + if (cfbuildver) CFStringGetCString(cfbuildver, buildver, sizeof(buildver), kCFStringEncodingUTF8); + sscanf(buildver, "%d%c%d", &major, &letter, &minor); + CFRelease(vers); + } + if (HINFO_SWstring) mDNS_snprintf(HINFO_SWstring, 256, "%s %s (%s), %s", prodname, prodvers, buildver, mDNSResponderVersionString); + return(major); + } + +mDNSlocal mStatus mDNSPlatformInit_setup(mDNS *const m) + { + mStatus err; + + m->hostlabel.c[0] = 0; + + char *HINFO_HWstring = "Macintosh"; + char HINFO_HWstring_buffer[256]; + int get_model[2] = { CTL_HW, HW_MODEL }; + size_t len_model = sizeof(HINFO_HWstring_buffer); + if (sysctl(get_model, 2, HINFO_HWstring_buffer, &len_model, NULL, 0) == 0) + HINFO_HWstring = HINFO_HWstring_buffer; + + char HINFO_SWstring[256] = ""; + if (mDNSMacOSXSystemBuildNumber(HINFO_SWstring) < 7) m->KnownBugs = mDNS_KnownBug_PhantomInterfaces; + + mDNSu32 hlen = mDNSPlatformStrLen(HINFO_HWstring); + mDNSu32 slen = mDNSPlatformStrLen(HINFO_SWstring); + if (hlen + slen < 254) + { + m->HIHardware.c[0] = hlen; + m->HISoftware.c[0] = slen; + mDNSPlatformMemCopy(HINFO_HWstring, &m->HIHardware.c[1], hlen); + mDNSPlatformMemCopy(HINFO_SWstring, &m->HISoftware.c[1], slen); + } + + m->p->InterfaceList = mDNSNULL; + m->p->userhostlabel.c[0] = 0; + UpdateInterfaceList(m); + SetupActiveInterfaces(m); + + err = WatchForNetworkChanges(m); + if (err) return(err); + + err = WatchForPowerChanges(m); + return(err); + } + +mDNSexport mStatus mDNSPlatformInit(mDNS *const m) + { + mStatus result = mDNSPlatformInit_setup(m); + // We don't do asynchronous initialization on OS X, so by the time we get here the setup will already + // have succeeded or failed -- so if it succeeded, we should just call mDNSCoreInitComplete() immediately + if (result == mStatus_NoError) mDNSCoreInitComplete(m, mStatus_NoError); + return(result); + } + +mDNSexport void mDNSPlatformClose(mDNS *const m) + { + if (m->p->PowerConnection) + { + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->PowerRLS, kCFRunLoopDefaultMode); + CFRunLoopSourceInvalidate(m->p->PowerRLS); + CFRelease(m->p->PowerRLS); + IODeregisterForSystemPower(&m->p->PowerNotifier); + m->p->PowerConnection = NULL; + m->p->PowerNotifier = NULL; + m->p->PowerRLS = NULL; + } + + if (m->p->Store) + { + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m->p->StoreRLS, kCFRunLoopDefaultMode); + CFRunLoopSourceInvalidate(m->p->StoreRLS); + CFRelease(m->p->StoreRLS); + CFRelease(m->p->Store); + m->p->Store = NULL; + m->p->StoreRLS = NULL; + } + + MarkAllInterfacesInactive(m); + ClearInactiveInterfaces(m); + } + +mDNSexport mDNSs32 mDNSPlatformOneSecond = 1000; + +mDNSexport mStatus mDNSPlatformTimeInit(mDNSs32 *timenow) + { + // Notes: Typical values for mach_timebase_info: + // tbi.numer = 1000 million + // tbi.denom = 33 million + // These are set such that (mach_absolute_time() * numer/denom) gives us nanoseconds; + // numer / denom = nanoseconds per hardware clock tick (e.g. 30); + // denom / numer = hardware clock ticks per nanosecond (e.g. 0.033) + // (denom*1000000) / numer = hardware clock ticks per millisecond (e.g. 33333) + // So: mach_absolute_time() / ((denom*1000000)/numer) = milliseconds + // + // Arithmetic notes: + // tbi.denom is at least 1, and not more than 2^32-1. + // Therefore (tbi.denom * 1000000) is at least one million, but cannot overflow a uint64_t. + // tbi.denom is at least 1, and not more than 2^32-1. + // Therefore clockdivisor should end up being a number roughly in the range 10^3 - 10^9. + // If clockdivisor is less than 10^3 then that means that the native clock frequency is less than 1MHz, + // which is unlikely on any current or future Macintosh. + // If clockdivisor is greater than 10^9 then that means the native clock frequency is greater than 1000GHz. + // When we ship Macs with clock frequencies above 1000GHz, we may have to update this code. + struct mach_timebase_info tbi; + kern_return_t result = mach_timebase_info(&tbi); + if (result != KERN_SUCCESS) return(result); + clockdivisor = ((uint64_t)tbi.denom * 1000000) / tbi.numer; + *timenow = mDNSPlatformTimeNow(); + return(mStatus_NoError); + } + +mDNSexport mDNSs32 mDNSPlatformTimeNow(void) + { + if (clockdivisor == 0) { LogMsg("mDNSPlatformTimeNow called before mDNSPlatformTimeInit"); return(0); } + return((mDNSs32)(mach_absolute_time() / clockdivisor)); + } + +// Locking is a no-op here, because we're single-threaded with a CFRunLoop, so we can never interrupt ourselves +mDNSexport void mDNSPlatformLock (const mDNS *const m) { (void)m; } +mDNSexport void mDNSPlatformUnlock (const mDNS *const m) { (void)m; } +mDNSexport void mDNSPlatformStrCopy(const void *src, void *dst) { strcpy((char *)dst, (char *)src); } +mDNSexport mDNSu32 mDNSPlatformStrLen (const void *src) { return(strlen((char*)src)); } +mDNSexport void mDNSPlatformMemCopy(const void *src, void *dst, mDNSu32 len) { memcpy(dst, src, len); } +mDNSexport mDNSBool mDNSPlatformMemSame(const void *src, const void *dst, mDNSu32 len) { return(memcmp(dst, src, len) == 0); } +mDNSexport void mDNSPlatformMemZero( void *dst, mDNSu32 len) { bzero(dst, len); } +mDNSexport void * mDNSPlatformMemAllocate(mDNSu32 len) { return(mallocL("mDNSPlatformMemAllocate", len)); } +mDNSexport void mDNSPlatformMemFree (void *mem) { freeL("mDNSPlatformMemFree", mem); } diff --git a/mDNSMacOSX/mDNSMacOSXPuma.c b/mDNSMacOSX/mDNSMacOSXPuma.c new file mode 100644 index 0000000..a23179d --- /dev/null +++ b/mDNSMacOSX/mDNSMacOSXPuma.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + * + * This file is not normally used. + * It can be conditionally compiled in by defining RUN_ON_PUMA_WITHOUT_IFADDRS + * in CFSocket.c. It is included mainly as sample code for people building + * for other platforms that (like Puma) lack the getifaddrs() call. + * NOTE: YOU CANNOT use this code to build an mDNSResponder daemon for Puma + * that works just like the Jaguar one, because Puma lacks other necessary + * functionality (like the LibInfo support to receive MIG messages from clients). + + Change History (most recent first): + +$Log: mDNSMacOSXPuma.c,v $ +Revision 1.4 2003/08/12 19:56:25 cheshire +Update to APSL 2.0 + +Revision 1.3 2003/07/02 21:19:51 cheshire + Update copyright notices, etc., in source code comments + +Revision 1.2 2002/09/21 20:44:51 zarzycki +Added APSL info + +Revision 1.1 2002/09/17 01:36:23 cheshire +Move Puma support to CFSocketPuma.c + + */ + +#include +#include +#define ifaddrs ifa_info +#ifndef ifa_broadaddr +#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ +#endif +#include + +/* Our own header for the programs that need interface configuration info. + Include this file, instead of "unp.h". */ + +#define IFA_NAME 16 /* same as IFNAMSIZ in */ +#define IFA_HADDR 8 /* allow for 64-bit EUI-64 in future */ + +struct ifa_info { + char ifa_name[IFA_NAME]; /* interface name, null terminated */ + u_char ifa_haddr[IFA_HADDR]; /* hardware address */ + u_short ifa_hlen; /* #bytes in hardware address: 0, 6, 8 */ + short ifa_flags; /* IFF_xxx constants from */ + short ifa_myflags; /* our own IFI_xxx flags */ + struct sockaddr *ifa_addr; /* primary address */ + struct sockaddr *ifa_brdaddr;/* broadcast address */ + struct sockaddr *ifa_dstaddr;/* destination address */ + struct ifa_info *ifa_next; /* next of these structures */ +}; + +#define IFI_ALIAS 1 /* ifa_addr is an alias */ + + /* function prototypes */ +struct ifa_info *get_ifa_info(int, int); +struct ifa_info *Get_ifa_info(int, int); +void free_ifa_info(struct ifa_info *); + +#define HAVE_SOCKADDR_SA_LEN 1 + +struct ifa_info * +get_ifa_info(int family, int doaliases) +{ + struct ifa_info *ifi, *ifihead, **ifipnext; + int sockfd, len, lastlen, flags, myflags; + char *ptr, *buf, lastname[IFNAMSIZ], *cptr; + struct ifconf ifc; + struct ifreq *ifr, ifrcopy; + struct sockaddr_in *sinptr; + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + + lastlen = 0; + len = 100 * sizeof(struct ifreq); /* initial buffer size guess */ + for ( ; ; ) { + buf = (char *) malloc(len); + ifc.ifc_len = len; + ifc.ifc_buf = buf; + if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { + if (errno != EINVAL || lastlen != 0) + debugf("ioctl error"); + } else { + if (ifc.ifc_len == lastlen) + break; /* success, len has not changed */ + lastlen = ifc.ifc_len; + } + len += 10 * sizeof(struct ifreq); /* increment */ + free(buf); + } + ifihead = NULL; + ifipnext = &ifihead; + lastname[0] = 0; +/* end get_ifa_info1 */ + +/* include get_ifa_info2 */ + for (ptr = buf; ptr < buf + ifc.ifc_len; ) { + ifr = (struct ifreq *) ptr; + +#ifdef HAVE_SOCKADDR_SA_LEN + len = MAX(sizeof(struct sockaddr), ifr->ifr_addr.sa_len); +#else + switch (ifr->ifr_addr.sa_family) { +#ifdef IPV6 + case AF_INET6: + len = sizeof(struct sockaddr_in6); + break; +#endif + case AF_INET: + default: + len = sizeof(struct sockaddr); + break; + } +#endif /* HAVE_SOCKADDR_SA_LEN */ + ptr += sizeof(ifr->ifr_name) + len; /* for next one in buffer */ + + if (ifr->ifr_addr.sa_family != family) + continue; /* ignore if not desired address family */ + + myflags = 0; + if ( (cptr = strchr(ifr->ifr_name, ':')) != NULL) + *cptr = 0; /* replace colon will null */ + if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) { + if (doaliases == 0) + continue; /* already processed this interface */ + myflags = IFI_ALIAS; + } + memcpy(lastname, ifr->ifr_name, IFNAMSIZ); + + ifrcopy = *ifr; + ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy); + flags = ifrcopy.ifr_flags; + if ((flags & IFF_UP) == 0) + continue; /* ignore if interface not up */ + + ifi = (struct ifa_info *) calloc(1, sizeof(struct ifa_info)); + *ifipnext = ifi; /* prev points to this new one */ + ifipnext = &ifi->ifa_next; /* pointer to next one goes here */ + + ifi->ifa_flags = flags; /* IFF_xxx values */ + ifi->ifa_myflags = myflags; /* IFI_xxx values */ + memcpy(ifi->ifa_name, ifr->ifr_name, IFA_NAME); + ifi->ifa_name[IFA_NAME-1] = '\0'; +/* end get_ifa_info2 */ +/* include get_ifa_info3 */ + switch (ifr->ifr_addr.sa_family) { + case AF_INET: + sinptr = (struct sockaddr_in *) &ifr->ifr_addr; + if (ifi->ifa_addr == NULL) { + ifi->ifa_addr = (struct sockaddr *) calloc(1, sizeof(struct sockaddr_in)); + memcpy(ifi->ifa_addr, sinptr, sizeof(struct sockaddr_in)); + +#ifdef SIOCGIFBRDADDR + if (flags & IFF_BROADCAST) { + ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy); + sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr; + ifi->ifa_brdaddr = (struct sockaddr *) calloc(1, sizeof(struct sockaddr_in)); + memcpy(ifi->ifa_brdaddr, sinptr, sizeof(struct sockaddr_in)); + } +#endif + +#ifdef SIOCGIFDSTADDR + if (flags & IFF_POINTOPOINT) { + ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy); + sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr; + ifi->ifa_dstaddr = (struct sockaddr *) calloc(1, sizeof(struct sockaddr_in)); + memcpy(ifi->ifa_dstaddr, sinptr, sizeof(struct sockaddr_in)); + } +#endif + } + break; + + default: + break; + } + } + free(buf); + return(ifihead); /* pointer to first structure in linked list */ +} +/* end get_ifa_info3 */ + +/* include free_ifa_info */ +mDNSlocal void freeifaddrs(struct ifa_info *ifihead) +{ + struct ifa_info *ifi, *ifinext; + + for (ifi = ifihead; ifi != NULL; ifi = ifinext) { + if (ifi->ifa_addr != NULL) + free(ifi->ifa_addr); + if (ifi->ifa_brdaddr != NULL) + free(ifi->ifa_brdaddr); + if (ifi->ifa_dstaddr != NULL) + free(ifi->ifa_dstaddr); + ifinext = ifi->ifa_next; /* can't fetch ifa_next after free() */ + free(ifi); /* the ifa_info{} itself */ + } +} +/* end free_ifa_info */ + +struct ifa_info * +Get_ifa_info(int family, int doaliases) +{ + struct ifa_info *ifi; + + if ( (ifi = get_ifa_info(family, doaliases)) == NULL) + debugf("get_ifa_info error"); + return(ifi); +} + +mDNSlocal int getifaddrs(struct ifa_info **ifalist) + { + *ifalist = get_ifa_info(PF_INET, false); + if( ifalist == nil ) + return -1; + else + return(0); + } diff --git a/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj b/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj index cf1844f..aa4ee90 100644 --- a/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj +++ b/mDNSMacOSX/mDNSResponder.pbproj/project.pbxproj @@ -91,10 +91,6 @@ path = dnssd_clientstub.c; refType = 2; }; - 0066920A04CC7AA80CCA2C71 = { - isa = PBXTargetDependency; - target = 0044D34804CC73600CCA2C71; - }; 00AD62A3032D799A0CCA2C71 = { buildPhases = ( 00AD62A4032D799A0CCA2C71, @@ -105,11 +101,11 @@ buildSettings = { FRAMEWORK_SEARCH_PATHS = ""; GCC_TREAT_WARNINGS_AS_ERRORS = YES; - HEADER_SEARCH_PATHS = "\"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\""; + HEADER_SEARCH_PATHS = "../mDNSShared \"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\""; LIBRARY_SEARCH_PATHS = ""; MACOSX_DEPLOYMENT_TARGET = 10.2; OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = "-no-cpp-precomp -D__MACOSX__ -DMDNS_DEBUGMSGS=1 -DmDNSResponderVersion=$(MVERS)"; + OTHER_CFLAGS = "-no-cpp-precomp -D__MACOSX__ -DMDNS_DEBUGMSGS=1 -DmDNSResponderVersion=$(MVERS) -DkDNSServiceFlagsRemove=0 -DkDNSServiceFlagsFinished=0"; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = mDNSResponder.debug; @@ -249,7 +245,8 @@ 00AD62BC032D7A160CCA2C71, 00AD62BD032D7A1B0CCA2C71, 00AD62BE032D7A1D0CCA2C71, - 0066920A04CC7AA80CCA2C71, + FF1B80C507AA1567000768F0, + FF1B80C607AA1569000768F0, ); isa = PBXAggregateTarget; name = "Build All"; @@ -333,10 +330,13 @@ 00AD62A3032D799A0CCA2C71, 6575FC1C022EB76000000109, 0044D34804CC73600CCA2C71, + FF518DC907AA0BA60096AE13, + FFEF84D207AA10DF00171646, ); }; 08FB7794FE84155DC02AAC07 = { children = ( + FF518DCB07AA0C330096AE13, 08FB7795FE84155DC02AAC07, 6575FC1F022EB78C00000109, 6575FBFE022EAFA800000109, @@ -370,6 +370,7 @@ 09AB6884FE841BABC02AAC07, 65713D46025A293200000109, 00CA213D02786FC30CCA2C71, + FFEF84D607AA115900171646, ); isa = PBXGroup; name = "External Frameworks and Libraries"; @@ -385,17 +386,18 @@ buildSettings = { FRAMEWORK_SEARCH_PATHS = ""; GCC_TREAT_WARNINGS_AS_ERRORS = YES; - HEADER_SEARCH_PATHS = "\"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\""; + HEADER_SEARCH_PATHS = "../mDNSShared \"$(APPLE_INTERNAL_DEVELOPER_DIR)/Headers\""; INSTALL_PATH = /usr/sbin; LIBRARY_SEARCH_PATHS = ""; MACOSX_DEPLOYMENT_TARGET = 10.2; - OTHER_CFLAGS = "-no-cpp-precomp -D__MACOSX__ -DmDNSResponderVersion=$(MVERS)"; + OTHER_CFLAGS = "-no-cpp-precomp -D__MACOSX__ -DmDNSResponderVersion=$(MVERS) -DkDNSServiceFlagsRemove=0 -DkDNSServiceFlagsFinished=0"; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = mDNSResponder; REZ_EXECUTABLE = YES; SECTORDER_FLAGS = ""; STRIPFLAGS = "-S"; + USE_GCC3_PFE_SUPPORT = NO; WARNING_CFLAGS = "-W -Wall -Wmissing-prototypes -Wno-four-char-constants -Wno-unknown-pragmas"; }; dependencies = ( @@ -484,6 +486,8 @@ 6575FC1D022EB76000000109, 00AD62B8032D799A0CCA2C71, 0044D34F04CC73600CCA2C71, + FF72324E07AA0CB30012EE6F, + FFEF84D307AA10DF00171646, ); isa = PBXGroup; name = Products; @@ -672,7 +676,7 @@ GCC_TREAT_WARNINGS_AS_ERRORS = YES; INSTALL_PATH = /usr/bin; MACOSX_DEPLOYMENT_TARGET = 10.2; - OTHER_CFLAGS = "-no-cpp-precomp -DmDNSResponderVersion=$(MVERS)"; + OTHER_CFLAGS = "-no-cpp-precomp -DmDNSResponderVersion=$(MVERS) -DkDNSServiceFlagsRemove=0"; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; PRODUCT_NAME = mDNS; @@ -822,6 +826,398 @@ settings = { }; }; +//F50 +//F51 +//F52 +//F53 +//F54 +//FF0 +//FF1 +//FF2 +//FF3 +//FF4 + FF1B80C507AA1567000768F0 = { + isa = PBXTargetDependency; + target = FF518DC907AA0BA60096AE13; + }; + FF1B80C607AA1569000768F0 = { + isa = PBXTargetDependency; + target = FFEF84D207AA10DF00171646; + }; + FF518DC607AA0BA60096AE13 = { + buildActionMask = 2147483647; + files = ( + FF518DD907AA0C330096AE13, + FF518DDA07AA0C330096AE13, + FF518DDB07AA0C330096AE13, + FF518DDC07AA0C330096AE13, + FF518DDD07AA0C330096AE13, + FF518DDE07AA0C330096AE13, + FF518DDF07AA0C330096AE13, + FF518DE007AA0C330096AE13, + FF518DE207AA0C330096AE13, + FF518DE307AA0C330096AE13, + FF518DE407AA0C330096AE13, + FF518DE507AA0C330096AE13, + ); + isa = PBXSourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FF518DC707AA0BA60096AE13 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXFrameworksBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FF518DC807AA0BA60096AE13 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXRezBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FF518DC907AA0BA60096AE13 = { + buildPhases = ( + FF518DC607AA0BA60096AE13, + FF518DC707AA0BA60096AE13, + FF518DC807AA0BA60096AE13, + FF72324F07AA0CC20012EE6F, + FF72325007AA0CCA0012EE6F, + ); + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + INSTALL_PATH = System/Library/Java/Extensions; + JAVA_ARCHIVE_CLASSES = YES; + JAVA_ARCHIVE_COMPRESSION = YES; + JAVA_ARCHIVE_TYPE = JAR; + JAVA_COMPILER_DEBUGGING_SYMBOLS = NO; + JAVA_COMPILER_TARGET_VM_VERSION = 1.2; + JAVA_SOURCE_SUBDIR = .; + LIBRARY_STYLE = STATIC; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOL_FLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = dns_sd; + REZ_EXECUTABLE = YES; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + }; + dependencies = ( + ); + isa = PBXLibraryTarget; + name = dns_sd.jar; + productInstallPath = System/Library/Java/Extensions; + productName = dns_sd.jar; + productReference = FF72324E07AA0CB30012EE6F; + }; + FF518DCB07AA0C330096AE13 = { + children = ( + FF518DCC07AA0C330096AE13, + FF518DCD07AA0C330096AE13, + FF518DCE07AA0C330096AE13, + FF518DCF07AA0C330096AE13, + FF518DD007AA0C330096AE13, + FF518DD107AA0C330096AE13, + FF518DD207AA0C330096AE13, + FF518DD307AA0C330096AE13, + FF518DD407AA0C330096AE13, + FF518DD507AA0C330096AE13, + FF518DD607AA0C330096AE13, + FF518DD707AA0C330096AE13, + FF518DD807AA0C330096AE13, + ); + isa = PBXGroup; + name = Java; + path = ../mDNSShared/Java; + refType = 2; + }; + FF518DCC07AA0C330096AE13 = { + fileEncoding = 30; + isa = PBXFileReference; + name = BaseListener.java; + path = ../mDNSShared/Java/BaseListener.java; + refType = 2; + }; + FF518DCD07AA0C330096AE13 = { + fileEncoding = 30; + isa = PBXFileReference; + name = BrowseListener.java; + path = ../mDNSShared/Java/BrowseListener.java; + refType = 2; + }; + FF518DCE07AA0C330096AE13 = { + fileEncoding = 30; + isa = PBXFileReference; + name = DNSRecord.java; + path = ../mDNSShared/Java/DNSRecord.java; + refType = 2; + }; + FF518DCF07AA0C330096AE13 = { + fileEncoding = 30; + isa = PBXFileReference; + name = DNSSD.java; + path = ../mDNSShared/Java/DNSSD.java; + refType = 2; + }; + FF518DD007AA0C330096AE13 = { + fileEncoding = 30; + isa = PBXFileReference; + name = DNSSDException.java; + path = ../mDNSShared/Java/DNSSDException.java; + refType = 2; + }; + FF518DD107AA0C330096AE13 = { + fileEncoding = 30; + isa = PBXFileReference; + name = DNSSDRegistration.java; + path = ../mDNSShared/Java/DNSSDRegistration.java; + refType = 2; + }; + FF518DD207AA0C330096AE13 = { + fileEncoding = 30; + isa = PBXFileReference; + name = DNSSDService.java; + path = ../mDNSShared/Java/DNSSDService.java; + refType = 2; + }; + FF518DD307AA0C330096AE13 = { + fileEncoding = 30; + isa = PBXFileReference; + name = DomainListener.java; + path = ../mDNSShared/Java/DomainListener.java; + refType = 2; + }; + FF518DD407AA0C330096AE13 = { + fileEncoding = 30; + isa = PBXFileReference; + name = JNISupport.c; + path = ../mDNSShared/Java/JNISupport.c; + refType = 2; + }; + FF518DD507AA0C330096AE13 = { + fileEncoding = 30; + isa = PBXFileReference; + name = QueryListener.java; + path = ../mDNSShared/Java/QueryListener.java; + refType = 2; + }; + FF518DD607AA0C330096AE13 = { + fileEncoding = 30; + isa = PBXFileReference; + name = RegisterListener.java; + path = ../mDNSShared/Java/RegisterListener.java; + refType = 2; + }; + FF518DD707AA0C330096AE13 = { + fileEncoding = 30; + isa = PBXFileReference; + name = ResolveListener.java; + path = ../mDNSShared/Java/ResolveListener.java; + refType = 2; + }; + FF518DD807AA0C330096AE13 = { + fileEncoding = 30; + isa = PBXFileReference; + name = TXTRecord.java; + path = ../mDNSShared/Java/TXTRecord.java; + refType = 2; + }; + FF518DD907AA0C330096AE13 = { + fileRef = FF518DCC07AA0C330096AE13; + isa = PBXBuildFile; + settings = { + }; + }; + FF518DDA07AA0C330096AE13 = { + fileRef = FF518DCD07AA0C330096AE13; + isa = PBXBuildFile; + settings = { + }; + }; + FF518DDB07AA0C330096AE13 = { + fileRef = FF518DCE07AA0C330096AE13; + isa = PBXBuildFile; + settings = { + }; + }; + FF518DDC07AA0C330096AE13 = { + fileRef = FF518DCF07AA0C330096AE13; + isa = PBXBuildFile; + settings = { + }; + }; + FF518DDD07AA0C330096AE13 = { + fileRef = FF518DD007AA0C330096AE13; + isa = PBXBuildFile; + settings = { + }; + }; + FF518DDE07AA0C330096AE13 = { + fileRef = FF518DD107AA0C330096AE13; + isa = PBXBuildFile; + settings = { + }; + }; + FF518DDF07AA0C330096AE13 = { + fileRef = FF518DD207AA0C330096AE13; + isa = PBXBuildFile; + settings = { + }; + }; + FF518DE007AA0C330096AE13 = { + fileRef = FF518DD307AA0C330096AE13; + isa = PBXBuildFile; + settings = { + }; + }; + FF518DE207AA0C330096AE13 = { + fileRef = FF518DD507AA0C330096AE13; + isa = PBXBuildFile; + settings = { + }; + }; + FF518DE307AA0C330096AE13 = { + fileRef = FF518DD607AA0C330096AE13; + isa = PBXBuildFile; + settings = { + }; + }; + FF518DE407AA0C330096AE13 = { + fileRef = FF518DD707AA0C330096AE13; + isa = PBXBuildFile; + settings = { + }; + }; + FF518DE507AA0C330096AE13 = { + fileRef = FF518DD807AA0C330096AE13; + isa = PBXBuildFile; + settings = { + }; + }; + FF72324E07AA0CB30012EE6F = { + includeInIndex = 0; + isa = PBXZipArchiveReference; + path = dns_sd.jar; + refType = 3; + }; + FF72324F07AA0CC20012EE6F = { + buildActionMask = 2147483647; + files = ( + ); + generatedFileNames = ( + ); + isa = PBXShellScriptBuildPhase; + neededFileNames = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "javah -force -classpath ${OBJROOT}/mDNSResponder.build/dns_sd.jar.build/JavaClasses/ -o ${OBJROOT}/mDNSResponder.build/dns_sd.jar.build/DNSSD.java.h com.apple.dnssd.AppleDNSSD com.apple.dnssd.AppleBrowser com.apple.dnssd.AppleResolver com.apple.dnssd.AppleRegistration com.apple.dnssd.AppleQuery com.apple.dnssd.AppleDomainEnum com.apple.dnssd.AppleService"; + }; + FF72325007AA0CCA0012EE6F = { + buildActionMask = 2147483647; + files = ( + ); + generatedFileNames = ( + ); + isa = PBXShellScriptBuildPhase; + neededFileNames = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "rm -f ${BUILD_DIR}/dns_sd"; + }; + FFEF84CE07AA10DF00171646 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXHeadersBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FFEF84CF07AA10DF00171646 = { + buildActionMask = 2147483647; + files = ( + FFEF84D407AA113100171646, + ); + isa = PBXSourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FFEF84D007AA10DF00171646 = { + buildActionMask = 2147483647; + files = ( + FFEF84D707AA115900171646, + ); + isa = PBXFrameworksBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FFEF84D107AA10DF00171646 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXRezBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + FFEF84D207AA10DF00171646 = { + buildPhases = ( + FFEF84CE07AA10DF00171646, + FFEF84CF07AA10DF00171646, + FFEF84D007AA10DF00171646, + FFEF84D107AA10DF00171646, + ); + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + HEADER_SEARCH_PATHS = "../mDNSShared \"$(SYSTEM_LIBRARY_DIR)/Frameworks/JavaVM.framework/Versions/A/Headers\" \"$(SYSTEM_LIBRARY_DIR)/Frameworks/JavaVM.framework/Versions/1.3.1/Headers\" \"$(OBJROOT)/mDNSResponder.build/dns_sd.jar.build\""; + INSTALL_PATH = /usr/lib/java; + LIBRARY_STYLE = DYNAMIC; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOL_FLAGS = ""; + OTHER_REZFLAGS = ""; + PRODUCT_NAME = libjdns_sd.jnilib; + REZ_EXECUTABLE = YES; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + }; + comments = "Platform-specific JNI library that bridges dns_sd.jar to ."; + dependencies = ( + FFEF84D807AA116400171646, + ); + isa = PBXLibraryTarget; + name = libjdns_sd.jnilib; + productInstallPath = /usr/lib/java; + productName = libjdns_sd.jnilib; + productReference = FFEF84D307AA10DF00171646; + }; + FFEF84D307AA10DF00171646 = { + isa = PBXLibraryReference; + path = libjdns_sd.jnilib; + refType = 3; + }; + FFEF84D407AA113100171646 = { + fileRef = FF518DD407AA0C330096AE13; + isa = PBXBuildFile; + settings = { + }; + }; + FFEF84D607AA115900171646 = { + isa = PBXFrameworkReference; + name = JavaVM.framework; + path = /System/Library/Frameworks/JavaVM.framework; + refType = 0; + }; + FFEF84D707AA115900171646 = { + fileRef = FFEF84D607AA115900171646; + isa = PBXBuildFile; + settings = { + }; + }; + FFEF84D807AA116400171646 = { + isa = PBXTargetDependency; + target = FF518DC907AA0BA60096AE13; + }; }; rootObject = 08FB7793FE84155DC02AAC07; } diff --git a/mDNSMacOSX/uds_daemon.c b/mDNSMacOSX/uds_daemon.c index 5cc63fc..b1d9eba 100644 --- a/mDNSMacOSX/uds_daemon.c +++ b/mDNSMacOSX/uds_daemon.c @@ -23,6 +23,16 @@ Change History (most recent first): $Log: uds_daemon.c,v $ +Revision 1.22.2.4 2005/01/28 05:41:45 cheshire + SUPan: Service advertisement in qmaster can yield zombie ads + +Revision 1.22.2.3 2005/01/28 04:03:24 cheshire + SUPan: Current method of doing subtypes causes name collisions +Summary: Pulled in ConstructServiceName, CountSubTypes and AllocateSubTypes from Tiger version. + +Revision 1.22.2.2 2004/06/18 17:28:19 cheshire + Current method of doing subtypes causes name collisions + Revision 1.22.2.1 2003/12/05 00:03:35 cheshire Use buffer size MAX_ESCAPED_DOMAIN_NAME instead of 256 @@ -120,7 +130,6 @@ typedef struct request_state CFRunLoopSourceRef rls; CFSocketRef sr; int sd; - int errfd; // state of read (in case message is read over several recv() calls) transfer_state ts; @@ -247,8 +256,8 @@ static void handle_regservice_request(request_state *request); static void regservice_termination_callback(void *context); static void process_service_registration(ServiceRecordSet *const srs); static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mStatus result); -static void handle_add_request(request_state *rstate); -static void handle_update_request(request_state *rstate); +static mStatus handle_add_request(request_state *rstate); +static mStatus handle_update_request(request_state *rstate); static mStatus gen_rr_response(domainname *servicename, mDNSInterfaceID id, request_state *request, reply_state **rep); static void append_reply(request_state *req, reply_state *rep); static int build_domainname_from_strings(domainname *srv, char *name, char *regtype, char *domain); @@ -258,12 +267,12 @@ static void handle_query_request(request_state *rstate); static mStatus do_question(request_state *rstate, domainname *name, uint32_t ifi, uint16_t rrtype, int16_t rrclass); static reply_state *format_enumeration_reply(request_state *rstate, char *domain, DNSServiceFlags flags, uint32_t ifi, DNSServiceErrorType err); static void handle_enum_request(request_state *rstate); -static void handle_regrecord_request(request_state *rstate); +static mStatus handle_regrecord_request(request_state *rstate); static void regrecord_callback(mDNS *const m, AuthRecord *const rr, mStatus result); static void connected_registration_termination(void *context); static void handle_reconfirm_request(request_state *rstate); static AuthRecord *read_rr_from_ipc_msg(char *msgbuf, int ttl); -static void handle_removerecord_request(request_state *rstate); +static mStatus handle_removerecord_request(request_state *rstate); static void reset_connected_rstate(request_state *rstate); static int deliver_error(request_state *rstate, mStatus err); static int deliver_async_error(request_state *rs, reply_op_t op, mStatus err); @@ -441,7 +450,7 @@ void udsserver_handle_configchange(void) for (req = all_requests; req; req = req->next) { srv = req->service; - if (srv->autoname && !SameDomainLabel(srv->name.c, mDNSStorage.nicelabel.c)) + if (srv && srv->autoname && !SameDomainLabel(srv->name.c, mDNSStorage.nicelabel.c)) { srv->rename_on_memfree = 1; err = mDNS_DeregisterService(&mDNSStorage, srv->srs); @@ -607,16 +616,19 @@ static void request_callback(CFSocketRef sr, CFSocketCallBackType t, CFDataRef d if (rstate->hdr.flags & IPC_FLAGS_NOREPLY) rstate->no_reply = 1; // check if primary socket is to be used for synchronous errors, else open new socket - if (rstate->hdr.flags & IPC_FLAGS_REUSE_SOCKET) - rstate->errfd = rstate->sd; - else - { - if ((rstate->errfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) + if ((rstate->hdr.flags & IPC_FLAGS_REUSE_SOCKET) == 0) + { + mStatus err = 0; + int nwritten; + int errfd = socket(AF_LOCAL, SOCK_STREAM, 0); + if (errfd < 0) { my_perror("ERROR: socket"); - exit(1); + abort_request(rstate); + unlink_request(rstate); + return; } - if (fcntl(rstate->errfd, F_SETFL, O_NONBLOCK) < 0) + if (fcntl(errfd, F_SETFL, O_NONBLOCK) < 0) { my_perror("ERROR: could not set control socket to non-blocking mode"); abort_request(rstate); @@ -627,32 +639,43 @@ static void request_callback(CFSocketRef sr, CFSocketCallBackType t, CFDataRef d bzero(&cliaddr, sizeof(cliaddr)); cliaddr.sun_family = AF_LOCAL; strcpy(cliaddr.sun_path, ctrl_path); - if (connect(rstate->errfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr)) < 0) + if (connect(errfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr)) < 0) { my_perror("ERROR: connect"); abort_request(rstate); unlink_request(rstate); } - } - - - - switch(rstate->hdr.op.request_op) - { - case resolve_request: handle_resolve_request(rstate); break; - case query_request: handle_query_request(rstate); break; - case browse_request: handle_browse_request(rstate); break; - case reg_service_request: handle_regservice_request(rstate); break; - case enumeration_request: handle_enum_request(rstate); break; - case reg_record_request: handle_regrecord_request(rstate); break; - case add_record_request: handle_add_request(rstate); break; - case update_record_request: handle_update_request(rstate); break; - case remove_record_request: handle_removerecord_request(rstate); break; - case reconfirm_record_request: handle_reconfirm_request(rstate); break; - default: - debugf("ERROR: udsserver_recv_request - unsupported request type: %d", rstate->hdr.op.request_op); - } + switch (rstate->hdr.op.request_op) + { + case reg_record_request: err = handle_regrecord_request (rstate); break; + case add_record_request: err = handle_add_request (rstate); break; + case update_record_request: err = handle_update_request (rstate); break; + case remove_record_request: err = handle_removerecord_request(rstate); break; + default: LogMsg("%3d: ERROR: udsserver_recv_request - unsupported request type: %d", rstate->sd, rstate->hdr.op); + } + + nwritten = send(errfd, &err, sizeof(err), 0); + // On a freshly-created Unix Domain Socket, the kernel should *never* fail to buffer a four-byte write for us. + // If not, we don't attempt to handle this failure, but we do log it. + if (nwritten < (int)sizeof(err)) + LogMsg("ERROR: failed to write error response back to caller: %d %d %s", nwritten, errno, strerror(errno)); + close(errfd); + reset_connected_rstate(rstate); // Reset ready to accept the next request on this pipe + } + else + { + switch (rstate->hdr.op.request_op) + { + case resolve_request: handle_resolve_request (rstate); break; + case query_request: handle_query_request (rstate); break; + case browse_request: handle_browse_request (rstate); break; + case reg_service_request: handle_regservice_request(rstate); break; + case enumeration_request: handle_enum_request (rstate); break; + case reconfirm_record_request: handle_reconfirm_request (rstate); break; + default: LogMsg("%3d: ERROR: udsserver_recv_request - unsupported request type: %d", rstate->sd, rstate->hdr.op); + } + } } // mDNS operation functions. Each operation has 3 associated functions - a request handler that parses @@ -986,6 +1009,77 @@ static void question_termination_callback(void *context) freeL("question_termination_callback", q); } +// If there's a comma followed by another character, +// FindFirstSubType overwrites the comma with a nul and returns the pointer to the next character. +// Otherwise, it returns a pointer to the final nul at the end of the string +static char *FindFirstSubType(char *p) + { + while (*p) + { + if (p[0] == '\\' && p[1]) p += 2; + else if (p[0] == ',' && p[1]) { *p++ = 0; return(p); } + else p++; + } + return(p); + } + +// If there's a comma followed by another character, +// FindNextSubType overwrites the comma with a nul and returns the pointer to the next character. +// If it finds an illegal unescaped dot in the subtype name, it returns mDNSNULL +// Otherwise, it returns a pointer to the final nul at the end of the string +static char *FindNextSubType(char *p) + { + while (*p) + { + if (p[0] == '\\' && p[1]) // If escape character + p += 2; // ignore following character + else if (p[0] == ',') // If we found a comma + { + if (p[1]) *p++ = 0; + return(p); + } + else if (p[0] == '.') + return(mDNSNULL); + else p++; + } + return(p); + } + +// Returns -1 if illegal subtype found +extern mDNSs32 CountSubTypes(char *regtype); +mDNSexport mDNSs32 CountSubTypes(char *regtype) + { + mDNSs32 NumSubTypes = 0; + char *stp = FindFirstSubType(regtype); + while (stp && *stp) // If we found a comma... + { + if (*stp == ',') return(-1); + NumSubTypes++; + stp = FindNextSubType(stp); + } + if (!stp) return(-1); + return(NumSubTypes); + } + +extern AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p); +mDNSexport AuthRecord *AllocateSubTypes(mDNSs32 NumSubTypes, char *p) + { + AuthRecord *st = mDNSNULL; + if (NumSubTypes) + { + mDNSs32 i; + st = mallocL("ServiceSubTypes", NumSubTypes * sizeof(AuthRecord)); + if (!st) return(mDNSNULL); + for (i = 0; i < NumSubTypes; i++) + { + while (*p) p++; + p++; + if (!MakeDomainNameFromDNSNameString(&st[i].resrec.name, p)) + { freeL("ServiceSubTypes", st); return(mDNSNULL); } + } + } + return(st); + } static void handle_browse_request(request_state *request) { @@ -994,6 +1088,7 @@ static void handle_browse_request(request_state *request) char regtype[MAX_ESCAPED_DOMAIN_NAME], domain[MAX_ESCAPED_DOMAIN_NAME]; DNSQuestion *q; domainname typedn, domdn; + mDNSs32 NumSubTypes; char *ptr; mStatus result; @@ -1027,7 +1122,13 @@ static void handle_browse_request(request_state *request) if (interfaceIndex && !InterfaceID) goto bad_param; q->QuestionContext = request; q->QuestionCallback = browse_result_callback; - if (!MakeDomainNameFromDNSNameString(&typedn, regtype) || + + typedn.c[0] = 0; + NumSubTypes = CountSubTypes(regtype); + if (NumSubTypes < 0 || NumSubTypes > 1) goto bad_param; + if (NumSubTypes == 1 && !AppendDNSNameString(&typedn, regtype + strlen(regtype) + 1)) goto bad_param; + + if (!AppendDNSNameString(&typedn, regtype) || !MakeDomainNameFromDNSNameString(&domdn, domain[0] ? domain : "local.")) goto bad_param; request->termination_context = q; @@ -1089,11 +1190,8 @@ static void handle_regservice_request(request_state *request) registered_service *r_srv; int srs_size; mStatus result; + mDNSs32 num_subtypes; - char *sub, *rtype_ptr; - int i, num_subtypes; - - if (request->ts != t_complete) { LogMsg("ERROR: handle_regservice_request - transfer state != t_complete"); @@ -1118,12 +1216,10 @@ static void handle_regservice_request(request_state *request) txtlen = get_short(&ptr); txtdata = get_rdata(&ptr, txtlen); - // count subtypes, replacing commas w/ whitespace - rtype_ptr = regtype; - num_subtypes = -1; - while((sub = strsep(&rtype_ptr, ","))) - if (*sub) num_subtypes++; - + // Check for sub-types after the service type + num_subtypes = CountSubTypes(regtype); + if (num_subtypes < 0) goto bad_param; + if (!name[0]) n = (&mDNSStorage)->nicelabel; else if (!MakeDomainLabelFromLiteralString(&n, name)) goto bad_param; @@ -1138,24 +1234,10 @@ static void handle_regservice_request(request_state *request) srs_size = sizeof(ServiceRecordSet) + (sizeof(RDataBody) > txtlen ? 0 : txtlen - sizeof(RDataBody)); r_srv->srs = mallocL("handle_regservice_request", srs_size); if (!r_srv->srs) goto malloc_error; - if (num_subtypes > 0) - { - r_srv->subtypes = mallocL("handle_regservice_request", num_subtypes * sizeof(AuthRecord)); - if (!r_srv->subtypes) goto malloc_error; - sub = regtype + strlen(regtype) + 1; - for (i = 0; i < num_subtypes; i++) - { - if (!MakeDomainNameFromDNSNameString(&(r_srv->subtypes + i)->resrec.name, sub)) - { - freeL("handle_regservice_request", r_srv->subtypes); - freeL("handle_regservice_request", r_srv); - r_srv = NULL; - goto bad_param; - } - sub += strlen(sub) + 1; - } - } - else r_srv->subtypes = NULL; + + r_srv->subtypes = AllocateSubTypes(num_subtypes, regtype); + if (num_subtypes && !r_srv->subtypes) + { freeL("handle_regservice_request", r_srv); r_srv = NULL; goto malloc_error; } r_srv->request = request; r_srv->autoname = (!name[0]); @@ -1272,7 +1354,7 @@ static void regservice_callback(mDNS *const m, ServiceRecordSet *const srs, mSta } } -static void handle_add_request(request_state *rstate) +static mStatus handle_add_request(request_state *rstate) { registered_record_entry *re; ExtraResourceRecord *extra; @@ -1287,7 +1369,7 @@ static void handle_add_request(request_state *rstate) { LogMsg("ERROR: handle_add_request - no service record set in request state"); deliver_error(rstate, mStatus_UnknownErr); - return; + return(-1); } ptr = rstate->msgdata; @@ -1313,14 +1395,12 @@ static void handle_add_request(request_state *rstate) extra->r.resrec.rdlength = rdlen; memcpy(&extra->r.rdatastorage.u.data, rdata, rdlen); result = mDNS_AddRecordToService(&mDNSStorage, srs , extra, &extra->r.rdatastorage, ttl); - deliver_error(rstate, result); - reset_connected_rstate(rstate); if (result) { freeL("handle_add_request", rstate->msgbuf); rstate->msgbuf = NULL; freeL("handle_add_request", extra); - return; + return(result); } re = mallocL("handle_add_request", sizeof(registered_record_entry)); if (!re) @@ -1332,9 +1412,10 @@ static void handle_add_request(request_state *rstate) re->rr = &extra->r; re->next = rstate->reg_recs; rstate->reg_recs = re; + return(result); } -static void handle_update_request(request_state *rstate) +static mStatus handle_update_request(request_state *rstate) { registered_record_entry *reptr; AuthRecord *rr; @@ -1349,7 +1430,7 @@ static void handle_update_request(request_state *rstate) if (!rstate->service) { deliver_error(rstate, mStatus_BadParamErr); - return; + return(-1); } rr = &rstate->service->srs->RR_TXT; } @@ -1378,8 +1459,7 @@ static void handle_update_request(request_state *rstate) newrd->MaxRDLength = rdsize; memcpy(&newrd->u, rdata, rdlen); result = mDNS_Update(&mDNSStorage, rr, ttl, rdlen, newrd, update_callback); - deliver_error(rstate, result); - reset_connected_rstate(rstate); + return(result); } static void update_callback(mDNS *const m, AuthRecord *const rr, RData *oldrd) @@ -1434,7 +1514,7 @@ static void regservice_termination_callback(void *context) } -static void handle_regrecord_request(request_state *rstate) +static mStatus handle_regrecord_request(request_state *rstate) { AuthRecord *rr; regrecord_callback_context *rcc; @@ -1446,17 +1526,13 @@ static void handle_regrecord_request(request_state *rstate) LogMsg("ERROR: handle_regrecord_request - transfer state != t_complete"); abort_request(rstate); unlink_request(rstate); - return; + return(-1); } rr = read_rr_from_ipc_msg(rstate->msgdata, 1); - if (!rr) - { - deliver_error(rstate, mStatus_BadParamErr); - return; - } + if (!rr) return(mStatus_BadParamErr); - rcc = mallocL("hanlde_regrecord_request", sizeof(regrecord_callback_context)); + rcc = mallocL("handle_regrecord_request", sizeof(regrecord_callback_context)); if (!rcc) goto malloc_error; rcc->rstate = rstate; rcc->client_context = rstate->hdr.client_context; @@ -1464,7 +1540,7 @@ static void handle_regrecord_request(request_state *rstate) rr->RecordCallback = regrecord_callback; // allocate registration entry, link into list - re = mallocL("hanlde_regrecord_request", sizeof(registered_record_entry)); + re = mallocL("handle_regrecord_request", sizeof(registered_record_entry)); if (!re) goto malloc_error; re->key = rstate->hdr.reg_index; re->rr = rr; @@ -1478,13 +1554,11 @@ static void handle_regrecord_request(request_state *rstate) } result = mDNS_Register(&mDNSStorage, rr); - deliver_error(rstate, result); - reset_connected_rstate(rstate); - return; + return(result); malloc_error: my_perror("ERROR: malloc"); - return; + return(-1); } static void regrecord_callback(mDNS *const m, AuthRecord *const rr, mStatus result) @@ -1534,7 +1608,7 @@ static void connected_registration_termination(void *context) -static void handle_removerecord_request(request_state *rstate) +static mStatus handle_removerecord_request(request_state *rstate) { registered_record_entry *reptr, *prev = NULL; mStatus err = mStatus_UnknownErr; @@ -1557,12 +1631,7 @@ static void handle_removerecord_request(request_state *rstate) prev = reptr; reptr = reptr->next; } - reset_connected_rstate(rstate); - if (deliver_error(rstate, err) < 0) - { - abort_request(rstate); - unlink_request(rstate); - } + return(err); } @@ -1598,7 +1667,7 @@ static void handle_enum_request(request_state *rstate) } // allocate context structures - def = mallocL("hanlde_enum_request", sizeof(domain_enum_t)); + def = mallocL("handle_enum_request", sizeof(domain_enum_t)); all = mallocL("handle_enum_request", sizeof(domain_enum_t)); term = mallocL("handle_enum_request", sizeof(enum_termination_t)); if (!def || !all || !term) @@ -2067,7 +2136,7 @@ static int deliver_error(request_state *rstate, mStatus err) int nwritten = -1; undelivered_error_t *undeliv; - nwritten = send(rstate->errfd, &err, sizeof(mStatus), 0); + nwritten = send(rstate->sd, &err, sizeof(mStatus), 0); if (nwritten < (int)sizeof(mStatus)) { if (errno == EINTR || errno == EAGAIN) @@ -2086,15 +2155,13 @@ static int deliver_error(request_state *rstate, mStatus err) } undeliv->err = err; undeliv->nwritten = nwritten; - undeliv->sd = rstate->errfd; + undeliv->sd = rstate->sd; rstate->u_err = undeliv; return 0; } - if (rstate->errfd != rstate->sd) close(rstate->errfd); return 0; error: - if (rstate->errfd != rstate->sd) close(rstate->errfd); return -1; } @@ -2166,8 +2233,6 @@ static void abort_request(request_state *rs) CFSocketInvalidate(rs->sr); CFRelease(rs->sr); rs->sd = -1; - if (rs->errfd >= 0) close(rs->errfd); - rs->errfd = -1; // free pending replies rep = rs->replies; diff --git a/mDNSPosix/ProxyResponder.c b/mDNSPosix/ProxyResponder.c index a982423..13f0d18 100644 --- a/mDNSPosix/ProxyResponder.c +++ b/mDNSPosix/ProxyResponder.c @@ -64,7 +64,7 @@ Revision 1.13 2003/04/18 22:46:12 cheshire Fix mistake in 1.8 -- INADDR_NONE is 0xFFFFFFFF, not 0 Revision 1.12 2003/04/16 02:11:07 cheshire -Fixed mDNS_RegisterNoSuchService non-existance function so that it works again +Fixed mDNS_RegisterNoSuchService non-existence function so that it works again Revision 1.11 2003/03/31 22:49:35 cheshire Add "$Log" header diff --git a/mDNSShared/Java/BaseListener.java b/mDNSShared/Java/BaseListener.java new file mode 100644 index 0000000..665263d --- /dev/null +++ b/mDNSShared/Java/BaseListener.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: BaseListener.java,v $ +Revision 1.2 2004/04/30 21:48:27 rpantos +Change line endings for CVS. + +Revision 1.1 2004/04/30 16:29:35 rpantos +First checked in. + + */ + + +package com.apple.dnssd; + + +/** A base class for DNSSD listeners. */ + +public interface BaseListener +{ + /** Called to report DNSSD operation failures.

+ + @param service + The service that encountered the failure. +

+ @param errorCode + Indicates the failure that occurred. See {@link DNSSDException} for error codes. + */ + void operationFailed( DNSSDService service, int errorCode); +} + diff --git a/mDNSShared/Java/BrowseListener.java b/mDNSShared/Java/BrowseListener.java new file mode 100644 index 0000000..5bda3ae --- /dev/null +++ b/mDNSShared/Java/BrowseListener.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: BrowseListener.java,v $ +Revision 1.2 2004/04/30 21:48:27 rpantos +Change line endings for CVS. + +Revision 1.1 2004/04/30 16:29:35 rpantos +First checked in. + + */ + + +package com.apple.dnssd; + + +/** A listener that receives results from {@link DNSSD#browse}. */ + +public interface BrowseListener extends BaseListener +{ + /** Called to report discovered services.

+ + @param browser + The active browse service. +

+ @param flags + Possible values are DNSSD.MORE_COMING. +

+ @param ifIndex + The interface on which the service is advertised. This index should be passed + to {@link DNSSD#resolve} when resolving the service. +

+ @param serviceName + The service name discovered. +

+ @param regType + The registration type, as passed in to DNSSD.browse(). +

+ @param domain + The domain in which the service was discovered. + */ + void serviceFound( DNSSDService browser, int flags, int ifIndex, + String serviceName, String regType, String domain); + + /** Called to report services which have been deregistered.

+ + @param browser + The active browse service. +

+ @param flags + Possible values are DNSSD.MORE_COMING. +

+ @param ifIndex + The interface on which the service is advertised. +

+ @param serviceName + The service name which has deregistered. +

+ @param regType + The registration type, as passed in to DNSSD.browse(). +

+ @param domain + The domain in which the service was discovered. + */ + void serviceLost( DNSSDService browser, int flags, int ifIndex, + String serviceName, String regType, String domain); +} + diff --git a/mDNSShared/Java/DNSRecord.java b/mDNSShared/Java/DNSRecord.java new file mode 100644 index 0000000..73e1626 --- /dev/null +++ b/mDNSShared/Java/DNSRecord.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: DNSRecord.java,v $ +Revision 1.2 2004/12/11 03:00:59 rpantos + Java DNSRecord API should be cleaned up + +Revision 1.1 2004/04/30 16:32:34 rpantos +First checked in. + + + */ + + +package com.apple.dnssd; + + +/** + Reference to a record returned by {@link DNSSDRegistration#addRecord}.

+ + Note: client is responsible for serializing access to these objects if + they are shared between concurrent threads. +*/ + +public interface DNSRecord +{ + /** Update a registered resource record.

+ The record must either be the primary txt record of a service registered via DNSSD.register(), + or a record added to a registered service via addRecord().

+ + @param flags + Currently unused, reserved for future use. +

+ @param rData + The new rdata to be contained in the updated resource record. +

+ @param ttl + The time to live of the updated resource record, in seconds. + */ + void update( int flags, byte[] rData, int ttl) + throws DNSSDException; + + /** Remove a registered resource record.

+ */ + void remove() + throws DNSSDException; +} + diff --git a/mDNSShared/Java/DNSSD.java b/mDNSShared/Java/DNSSD.java new file mode 100644 index 0000000..831b4b4 --- /dev/null +++ b/mDNSShared/Java/DNSSD.java @@ -0,0 +1,833 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: DNSSD.java,v $ +Revision 1.4 2004/12/11 03:00:59 rpantos + Java DNSRecord API should be cleaned up + +Revision 1.3 2004/11/12 03:23:08 rpantos +rdar://problem/3809541 implement getIfIndexForName, getNameForIfIndex. + +Revision 1.2 2004/05/20 17:43:18 cheshire +Fix invalid UTF-8 characters in file + +Revision 1.1 2004/04/30 16:32:34 rpantos +First checked in. + + + This file declares and implements DNSSD, the central Java factory class + for doing DNS Service Discovery. It includes the mostly-abstract public + interface, as well as the Apple* implementation subclasses. + + To do: + - implement network interface mappings + - RegisterRecord + */ + + +package com.apple.dnssd; + + +/** + DNSSD provides access to DNS Service Discovery features of ZeroConf networking.

+ + It is a factory class that is used to invoke registration and discovery-related + operations. Most operations are non-blocking; clients are called back through an interface + with the result of an operation. Callbacks are made from a separate worker thread.

+ + For example, in this program

+


+    class   MyClient implements BrowseListener {
+        void    lookForWebServers() {
+            myBrowser = DNSSD.browse("_http_.tcp", this);
+        }
+    
+        public void serviceFound(DNSSDService browser, int flags, int ifIndex, 
+                            String serviceName, String regType, String domain) {}
+        ... 
+    }
+ MyClient.serviceFound() would be called for every HTTP server discovered in the + default browse domain(s). +*/ + +abstract public class DNSSD +{ + /** Flag indicates to a {@link BrowseListener} that another result is + queued. Applications should not update their UI to display browse + results if the MORE_COMING flag is set; they will be called at least once + more with the flag clear. + */ + public static final int MORE_COMING = ( 1 << 0 ); + + /** If flag is set in a {@link DomainListener} callback, indicates that the result is the default domain. */ + public static final int DEFAULT = ( 1 << 2 ); + + /** If flag is set, a name conflict will trigger an exception when registering non-shared records.

+ A name must be explicitly specified when registering a service if this bit is set + (i.e. the default name may not not be used). + */ + public static final int NO_AUTO_RENAME = ( 1 << 3 ); + + /** If flag is set, allow multiple records with this name on the network (e.g. PTR records) + when registering individual records on a {@link DNSSDRegistration}. + */ + public static final int SHARED = ( 1 << 4 ); + + /** If flag is set, records with this name must be unique on the network (e.g. SRV records). */ + public static final int UNIQUE = ( 1 << 5 ); + + /** Set flag when calling enumerateDomains() to restrict results to domains recommended for browsing. */ + public static final int BROWSE_DOMAINS = ( 1 << 6 ); + /** Set flag when calling enumerateDomains() to restrict results to domains recommended for registration. */ + public static final int REGISTRATION_DOMAINS = ( 1 << 7 ); + + /** Maximum length, in bytes, of a domain name represented as an escaped C-String. */ + public static final int MAX_DOMAIN_NAME = 1005; + + /** Pass for ifIndex to specify all available interfaces. */ + public static final int ALL_INTERFACES = 0; + + /** Pass for ifIndex to specify the localhost interface. */ + public static final int LOCALHOST_ONLY = -1; + + /** Browse for instances of a service.

+ + Note: browsing consumes network bandwidth. Call {@link DNSSDService#stop} when you have finished browsing.

+ + @param flags + Currently ignored, reserved for future use. +

+ @param ifIndex + If non-zero, specifies the interface on which to browse for services + (the index for a given interface is determined via the if_nametoindex() + family of calls.) Most applications will pass 0 to browse on all available + interfaces. Pass -1 to only browse for services provided on the local host. +

+ @param regType + The registration type being browsed for followed by the protocol, separated by a + dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". +

+ @param domain + If non-null, specifies the domain on which to browse for services. + Most applications will not specify a domain, instead browsing on the + default domain(s). +

+ @param listener + This object will get called when instances of the service are discovered (or disappear). +

+ @return A {@link DNSSDService} that represents the active browse operation. + + @throws SecurityException If a security manager is present and denies RuntimePermission("getDNSSDInstance"). + @see RuntimePermission + */ + public static DNSSDService browse( int flags, int ifIndex, String regType, String domain, BrowseListener listener) + throws DNSSDException + { return getInstance()._makeBrowser( flags, ifIndex, regType, domain, listener); } + + /** Browse for instances of a service. Use default flags, ifIndex and domain.

+ + @param regType + The registration type being browsed for followed by the protocol, separated by a + dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". +

+ @param listener + This object will get called when instances of the service are discovered (or disappear). +

+ @return A {@link DNSSDService} that represents the active browse operation. + + @throws SecurityException If a security manager is present and denies RuntimePermission("getDNSSDInstance"). + @see RuntimePermission + */ + public static DNSSDService browse( String regType, BrowseListener listener) + throws DNSSDException + { return browse( 0, 0, regType, "", listener); } + + /** Resolve a service name discovered via browse() to a target host name, port number, and txt record.

+ + Note: Applications should NOT use resolve() solely for txt record monitoring - use + queryRecord() instead, as it is more efficient for this task.

+ + Note: When the desired results have been returned, the client MUST terminate the resolve by + calling {@link DNSSDService#stop}.

+ + Note: resolve() behaves correctly for typical services that have a single SRV record and + a single TXT record (the TXT record may be empty.) To resolve non-standard services with + multiple SRV or TXT records, use queryRecord().

+ + @param flags + Currently ignored, reserved for future use. +

+ @param ifIndex + The interface on which to resolve the service. The client should + pass the interface on which the serviceName was discovered (i.e. + the ifIndex passed to the serviceFound() callback) + or 0 to resolve the named service on all available interfaces. +

+ @param serviceName + The servicename to be resolved. +

+ @param regType + The registration type being resolved followed by the protocol, separated by a + dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". +

+ @param domain + The domain on which the service is registered, i.e. the domain passed + to the serviceFound() callback. +

+ @param listener + This object will get called when the service is resolved. +

+ @return A {@link DNSSDService} that represents the active resolve operation. + + @throws SecurityException If a security manager is present and denies RuntimePermission("getDNSSDInstance"). + @see RuntimePermission + */ + public static DNSSDService resolve( int flags, int ifIndex, String serviceName, String regType, + String domain, ResolveListener listener) + throws DNSSDException + { return getInstance()._resolve( flags, ifIndex, serviceName, regType, domain, listener); } + + /** Register a service, to be discovered via browse() and resolve() calls.

+ @param flags + Possible values are: NO_AUTO_RENAME. +

+ @param ifIndex + If non-zero, specifies the interface on which to register the service + (the index for a given interface is determined via the if_nametoindex() + family of calls.) Most applications will pass 0 to register on all + available interfaces. Pass -1 to register a service only on the local + machine (service will not be visible to remote hosts). +

+ @param serviceName + If non-null, specifies the service name to be registered. + Applications need not specify a name, in which case the + computer name is used (this name is communicated to the client via + the serviceRegistered() callback). +

+ @param regType + The registration type being registered followed by the protocol, separated by a + dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". +

+ @param domain + If non-null, specifies the domain on which to advertise the service. + Most applications will not specify a domain, instead automatically + registering in the default domain(s). +

+ @param host + If non-null, specifies the SRV target host name. Most applications + will not specify a host, instead automatically using the machine's + default host name(s). Note that specifying a non-null host does NOT + create an address record for that host - the application is responsible + for ensuring that the appropriate address record exists, or creating it + via {@link DNSSDRegistration#addRecord}. +

+ @param port + The port on which the service accepts connections. Pass 0 for a + "placeholder" service (i.e. a service that will not be discovered by + browsing, but will cause a name conflict if another client tries to + register that same name.) Most clients will not use placeholder services. +

+ @param txtRecord + The txt record rdata. May be null. Note that a non-null txtRecord + MUST be a properly formatted DNS TXT record, i.e. <length byte> <data> + <length byte> <data> ... +

+ @param listener + This object will get called when the service is registered. +

+ @return A {@link DNSSDRegistration} that controls the active registration. + + @throws SecurityException If a security manager is present and denies RuntimePermission("getDNSSDInstance"). + @see RuntimePermission + */ + public static DNSSDRegistration register( int flags, int ifIndex, String serviceName, String regType, + String domain, String host, int port, TXTRecord txtRecord, RegisterListener listener) + throws DNSSDException + { return getInstance()._register( flags, ifIndex, serviceName, regType, domain, host, port, txtRecord, listener); } + + /** Register a service, to be discovered via browse() and resolve() calls. Use default flags, ifIndex, domain, host and txtRecord.

+ @param serviceName + If non-null, specifies the service name to be registered. + Applications need not specify a name, in which case the + computer name is used (this name is communicated to the client via + the serviceRegistered() callback). +

+ @param regType + The registration type being registered followed by the protocol, separated by a + dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". +

+ @param port + The port on which the service accepts connections. Pass 0 for a + "placeholder" service (i.e. a service that will not be discovered by + browsing, but will cause a name conflict if another client tries to + register that same name.) Most clients will not use placeholder services. +

+ @param listener + This object will get called when the service is registered. +

+ @return A {@link DNSSDRegistration} that controls the active registration. + + @throws SecurityException If a security manager is present and denies RuntimePermission("getDNSSDInstance"). + @see RuntimePermission + */ + public static DNSSDRegistration register( String serviceName, String regType, int port, RegisterListener listener) + throws DNSSDException + { return register( 0, 0, serviceName, regType, null, null, port, null, listener); } + + /** Query for an arbitrary DNS record.

+ @param flags + Possible values are: MORE_COMING. +

+ @param ifIndex + If non-zero, specifies the interface on which to issue the query + (the index for a given interface is determined via the if_nametoindex() + family of calls.) Passing 0 causes the name to be queried for on all + interfaces. Passing -1 causes the name to be queried for only on the + local host. +

+ @param serviceName + The full domain name of the resource record to be queried for. +

+ @param rrtype + The numerical type of the resource record to be queried for (e.g. PTR, SRV, etc) + as defined in nameser.h. +

+ @param rrclass + The class of the resource record, as defined in nameser.h + (usually 1 for the Internet class). +

+ @param listener + This object will get called when the query completes. +

+ @return A {@link DNSSDService} that controls the active query. + + @throws SecurityException If a security manager is present and denies RuntimePermission("getDNSSDInstance"). + @see RuntimePermission + */ + public static DNSSDService queryRecord( int flags, int ifIndex, String serviceName, int rrtype, + int rrclass, QueryListener listener) + throws DNSSDException + { return getInstance()._queryRecord( flags, ifIndex, serviceName, rrtype, rrclass, listener); } + + /** Asynchronously enumerate domains available for browsing and registration.

+ + Currently, the only domain returned is "local.", but other domains will be returned in future.

+ + The enumeration MUST be cancelled by calling {@link DNSSDService#stop} when no more domains + are to be found.

+ @param flags + Possible values are: BROWSE_DOMAINS, REGISTRATION_DOMAINS. +

+ @param ifIndex + If non-zero, specifies the interface on which to look for domains. + (the index for a given interface is determined via the if_nametoindex() + family of calls.) Most applications will pass 0 to enumerate domains on + all interfaces. +

+ @param listener + This object will get called when domains are found. +

+ @return A {@link DNSSDService} that controls the active enumeration. + + @throws SecurityException If a security manager is present and denies RuntimePermission("getDNSSDInstance"). + @see RuntimePermission + */ + public static DNSSDService enumerateDomains( int flags, int ifIndex, DomainListener listener) + throws DNSSDException + { return getInstance()._enumerateDomains( flags, ifIndex, listener); } + + /** Concatenate a three-part domain name (as provided to the listeners) into a + properly-escaped full domain name. Note that strings passed to listeners are + ALREADY ESCAPED where necessary.

+ @param serviceName + The service name - any dots or slashes must NOT be escaped. + May be null (to construct a PTR record name, e.g. "_ftp._tcp.apple.com"). +

+ @param regType + The registration type followed by the protocol, separated by a dot (e.g. "_ftp._tcp"). +

+ @param domain + The domain name, e.g. "apple.com". Any literal dots or backslashes must be escaped. +

+ @return The full domain name. + + @throws SecurityException If a security manager is present and denies RuntimePermission("getDNSSDInstance"). + @see RuntimePermission + */ + public static String constructFullName( String serviceName, String regType, String domain) + throws DNSSDException + { return getInstance()._constructFullName( serviceName, regType, domain); } + + /** Instruct the daemon to verify the validity of a resource record that appears to + be out of date. (e.g. because tcp connection to a service's target failed.)

+ + Causes the record to be flushed from the daemon's cache (as well as all other + daemons' caches on the network) if the record is determined to be invalid.

+ @param flags + Currently unused, reserved for future use. +

+ @param ifIndex + If non-zero, specifies the interface on which to reconfirm the record + (the index for a given interface is determined via the if_nametoindex() + family of calls.) Passing 0 causes the name to be reconfirmed on all + interfaces. Passing -1 causes the name to be reconfirmed only on the + local host. +

+ @param fullName + The resource record's full domain name. +

+ @param rrtype + The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h. +

+ @param rrclass + The class of the resource record, as defined in nameser.h (usually 1). +

+ @param rdata + The raw rdata of the resource record. + + @throws SecurityException If a security manager is present and denies RuntimePermission("getDNSSDInstance"). + @see RuntimePermission + */ + public static void reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype, + int rrclass, byte[] rdata) + { getInstance()._reconfirmRecord( flags, ifIndex, fullName, rrtype, rrclass, rdata); } + + /** Return the canonical name of a particular interface index.

+ @param ifIndex + A valid interface index. Must not be ALL_INTERFACES. +

+ @return The name of the interface, which should match java.net.NetworkInterface.getName(). + + @throws SecurityException If a security manager is present and denies RuntimePermission("getDNSSDInstance"). + @see RuntimePermission + */ + public static String getNameForIfIndex( int ifIndex) + { return getInstance()._getNameForIfIndex( ifIndex); } + + /** Return the index of a named interface.

+ @param ifName + A valid interface name. An example is java.net.NetworkInterface.getName(). +

+ @return The interface index. + + @throws SecurityException If a security manager is present and denies RuntimePermission("getDNSSDInstance"). + @see RuntimePermission + */ + public static int getIfIndexForName( String ifName) + { return getInstance()._getIfIndexForName( ifName); } + + protected DNSSD() {} // prevent direct instantiation + + /** Return the single instance of DNSSD. */ + static protected final DNSSD getInstance() + { + SecurityManager sm = System.getSecurityManager(); + if ( sm != null) + sm.checkPermission( new RuntimePermission( "getDNSSDInstance")); + return fInstance; + } + + abstract protected DNSSDService _makeBrowser( int flags, int ifIndex, String regType, String domain, BrowseListener listener) + throws DNSSDException; + + abstract protected DNSSDService _resolve( int flags, int ifIndex, String serviceName, String regType, + String domain, ResolveListener listener) + throws DNSSDException; + + abstract protected DNSSDRegistration _register( int flags, int ifIndex, String serviceName, String regType, + String domain, String host, int port, TXTRecord txtRecord, RegisterListener listener) + throws DNSSDException; + + abstract protected DNSSDService _queryRecord( int flags, int ifIndex, String serviceName, int rrtype, + int rrclass, QueryListener listener) + throws DNSSDException; + + abstract protected DNSSDService _enumerateDomains( int flags, int ifIndex, DomainListener listener) + throws DNSSDException; + + abstract protected String _constructFullName( String serviceName, String regType, String domain) + throws DNSSDException; + + abstract protected void _reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype, + int rrclass, byte[] rdata); + + abstract protected String _getNameForIfIndex( int ifIndex); + + abstract protected int _getIfIndexForName( String ifName); + + protected static DNSSD fInstance; + + static + { + try + { + String name = System.getProperty( "com.apple.dnssd.DNSSD" ); + if( name == null ) + name = "com.apple.dnssd.AppleDNSSD"; // Fall back to Apple-provided class. + fInstance = (DNSSD) Class.forName( name ).newInstance(); + } + catch( Exception e ) + { + throw new InternalError( "cannot instantiate DNSSD" + e ); + } + } +} + + +// Concrete implementation of DNSSDException +class AppleDNSSDException extends DNSSDException +{ + public AppleDNSSDException( int errorCode) { fErrorCode = errorCode; } + + public int getErrorCode() { return fErrorCode; } + + public String getMessage() + { + final String kMessages[] = { // should probably be put into a resource or something + "UNKNOWN", + "NO_SUCH_NAME", + "NO_MEMORY", + "BAD_PARAM", + "BAD_REFERENCE", + "BAD_STATE", + "BAD_FLAGS", + "UNSUPPORTED", + "NOT_INITIALIZED", + "", // there is NO number 6 + "ALREADY_REGISTERED", + "NAME_CONFLICT", + "INVALID", + "", // another MIA + "INCOMPATIBLE", + "BAD_INTERFACE_INDEX" + }; + + if ( fErrorCode <= UNKNOWN && fErrorCode > ( UNKNOWN - kMessages.length)) + { + return "DNS-SD Error " + String.valueOf( fErrorCode) + ": " + kMessages[ UNKNOWN - fErrorCode]; + } + else + return super.getMessage() + "(" + String.valueOf( fErrorCode) + ")"; + } + + protected int fErrorCode; +} + +// The concrete, default implementation. +class AppleDNSSD extends DNSSD +{ + static + { + System.loadLibrary( "jdns_sd"); + + int libInitResult = InitLibrary( 1); + + if ( libInitResult != DNSSDException.NO_ERROR) + throw new InternalError( "cannot instantiate DNSSD: " + new AppleDNSSDException( libInitResult).getMessage()); + } + + static public boolean hasAutoCallbacks; // Set by InitLibrary() to value of AUTO_CALLBACKS + + protected DNSSDService _makeBrowser( int flags, int ifIndex, String regType, String domain, BrowseListener client) + throws DNSSDException + { + return new AppleBrowser( flags, ifIndex, regType, domain, client); + } + + protected DNSSDService _resolve( int flags, int ifIndex, String serviceName, String regType, + String domain, ResolveListener client) + throws DNSSDException + { + return new AppleResolver( flags, ifIndex, serviceName, regType, domain, client); + } + + protected DNSSDRegistration _register( int flags, int ifIndex, String serviceName, String regType, + String domain, String host, int port, TXTRecord txtRecord, RegisterListener client) + throws DNSSDException + { + return new AppleRegistration( flags, ifIndex, serviceName, regType, domain, host, port, + ( txtRecord != null) ? txtRecord.getRawBytes() : null, client); + } + + protected DNSSDService _queryRecord( int flags, int ifIndex, String serviceName, int rrtype, + int rrclass, QueryListener client) + throws DNSSDException + { + return new AppleQuery( flags, ifIndex, serviceName, rrtype, rrclass, client); + } + + protected DNSSDService _enumerateDomains( int flags, int ifIndex, DomainListener listener) + throws DNSSDException + { + return new AppleDomainEnum( flags, ifIndex, listener); + } + + protected String _constructFullName( String serviceName, String regType, String domain) + throws DNSSDException + { + String[] responseHolder = new String[1]; // lame maneuver to get around Java's lack of reference parameters + + int rc = ConstructName( serviceName, regType, domain, responseHolder); + if ( rc != 0) + throw new AppleDNSSDException( rc); + + return responseHolder[0]; + } + + protected void _reconfirmRecord( int flags, int ifIndex, String fullName, int rrtype, + int rrclass, byte[] rdata) + { + ReconfirmRecord( flags, ifIndex, fullName, rrtype, rrclass, rdata); + } + + protected String _getNameForIfIndex( int ifIndex) + { + return GetNameForIfIndex( ifIndex); + } + + protected int _getIfIndexForName( String ifName) + { + return GetIfIndexForName( ifName); + } + + + protected native int ConstructName( String serviceName, String regType, String domain, String[] pOut); + + protected native void ReconfirmRecord( int flags, int ifIndex, String fullName, int rrtype, + int rrclass, byte[] rdata); + + protected native String GetNameForIfIndex( int ifIndex); + + protected native int GetIfIndexForName( String ifName); + + protected static native int InitLibrary( int callerVersion); +} + +class AppleService implements DNSSDService, Runnable +{ + public AppleService() { fNativeContext = 0; } + + public void stop() { this.HaltOperation(); } + + public void finalize() throws Throwable + { + this.stop(); + super.finalize(); + } + + /* The run() method is used internally to schedule an update from another thread */ + public void run() + { + this.ProcessResults(); + } + + /* Block for timeout ms (or forever if -1). Returns 1 if data present, 0 if timed out, -1 if not browsing. */ + protected native int BlockForData( int msTimeout); + + /* Call ProcessResults when data appears on socket descriptor. */ + protected native void ProcessResults(); + + protected native void HaltOperation(); + + protected void ThrowOnErr( int rc) throws DNSSDException + { + if ( rc != 0) + throw new AppleDNSSDException( rc); + } + + protected int /* warning */ fNativeContext; // Private storage for native side +} + + +// A ServiceThread calls AppleService.BlockForData() and schedules its client +// when data appears. +class ServiceThread extends Thread +{ + public ServiceThread( AppleService owner) { fOwner = owner; } + + public void run() + { + int result; + + while ( true ) + { + result = fOwner.BlockForData( -1); + if ( result == 1) + { + fOwner.run(); + } + else + break; // terminate thread + } + } + + protected AppleService fOwner; +} + + +class AppleBrowser extends AppleService +{ + public AppleBrowser( int flags, int ifIndex, String regType, String domain, BrowseListener client) + throws DNSSDException + { + fClient = client; + this.ThrowOnErr( this.CreateBrowser( flags, ifIndex, regType, domain)); + if ( !AppleDNSSD.hasAutoCallbacks) + new ServiceThread( this).start(); + } + + // Sets fNativeContext. Returns non-zero on error. + protected native int CreateBrowser( int flags, int ifIndex, String regType, String domain); + + protected BrowseListener fClient; +} + +class AppleResolver extends AppleService +{ + public AppleResolver( int flags, int ifIndex, String serviceName, String regType, + String domain, ResolveListener client) + throws DNSSDException + { + fClient = client; + this.ThrowOnErr( this.CreateResolver( flags, ifIndex, serviceName, regType, domain)); + if ( !AppleDNSSD.hasAutoCallbacks) + new ServiceThread( this).start(); + } + + // Sets fNativeContext. Returns non-zero on error. + protected native int CreateResolver( int flags, int ifIndex, String serviceName, String regType, + String domain); + + protected ResolveListener fClient; +} + +// An AppleDNSRecord is a simple wrapper around a dns_sd DNSRecord. +class AppleDNSRecord implements DNSRecord +{ + public AppleDNSRecord( AppleService owner) + { + fOwner = owner; + fRecord = 0; // record always starts out empty + } + + public void update( int flags, byte[] rData, int ttl) + throws DNSSDException + { + this.ThrowOnErr( this.Update( flags, rData, ttl)); + } + + public void remove() + throws DNSSDException + { + this.ThrowOnErr( this.Remove()); + } + + protected int fRecord; // Really a DNSRecord; sizeof(int) == sizeof(void*) ? + protected AppleService fOwner; + + protected void ThrowOnErr( int rc) throws DNSSDException + { + if ( rc != 0) + throw new AppleDNSSDException( rc); + } + + protected native int Update( int flags, byte[] rData, int ttl); + + protected native int Remove(); +} + +class AppleRegistration extends AppleService implements DNSSDRegistration +{ + public AppleRegistration( int flags, int ifIndex, String serviceName, String regType, String domain, + String host, int port, byte[] txtRecord, RegisterListener client) + throws DNSSDException + { + fClient = client; + this.ThrowOnErr( this.BeginRegister( ifIndex, flags, serviceName, regType, domain, host, port, txtRecord)); + if ( !AppleDNSSD.hasAutoCallbacks) + new ServiceThread( this).start(); + } + + public DNSRecord addRecord( int flags, int rrType, byte[] rData, int ttl) + throws DNSSDException + { + AppleDNSRecord newRecord = new AppleDNSRecord( this); + + this.ThrowOnErr( this.AddRecord( flags, rrType, rData, ttl, newRecord)); + + return newRecord; + } + + public DNSRecord getTXTRecord() + throws DNSSDException + { + return new AppleDNSRecord( this); // A record with ref 0 is understood to be primary TXT record + } + + // Sets fNativeContext. Returns non-zero on error. + protected native int BeginRegister( int ifIndex, int flags, String serviceName, String regType, + String domain, String host, int port, byte[] txtRecord); + + // Sets fNativeContext. Returns non-zero on error. + protected native int AddRecord( int flags, int rrType, byte[] rData, int ttl, AppleDNSRecord destObj); + + protected RegisterListener fClient; +} + +class AppleQuery extends AppleService +{ + public AppleQuery( int flags, int ifIndex, String serviceName, int rrtype, + int rrclass, QueryListener client) + throws DNSSDException + { + fClient = client; + this.ThrowOnErr( this.CreateQuery( flags, ifIndex, serviceName, rrtype, rrclass)); + if ( !AppleDNSSD.hasAutoCallbacks) + new ServiceThread( this).start(); + } + + // Sets fNativeContext. Returns non-zero on error. + protected native int CreateQuery( int flags, int ifIndex, String serviceName, int rrtype, int rrclass); + + protected QueryListener fClient; +} + +class AppleDomainEnum extends AppleService +{ + public AppleDomainEnum( int flags, int ifIndex, DomainListener listener) + throws DNSSDException + { + fClient = listener; + this.ThrowOnErr( this.BeginEnum( flags, ifIndex)); + if ( !AppleDNSSD.hasAutoCallbacks) + new ServiceThread( this).start(); + } + + // Sets fNativeContext. Returns non-zero on error. + protected native int BeginEnum( int flags, int ifIndex); + + protected DomainListener fClient; +} + + diff --git a/mDNSShared/Java/DNSSDException.java b/mDNSShared/Java/DNSSDException.java new file mode 100644 index 0000000..595e405 --- /dev/null +++ b/mDNSShared/Java/DNSSDException.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: DNSSDException.java,v $ +Revision 1.2 2004/04/30 21:48:27 rpantos +Change line endings for CVS. + +Revision 1.1 2004/04/30 16:29:35 rpantos +First checked in. + +*/ + +package com.apple.dnssd; + + +/** + Used to report various DNS-SD-related error conditions. +*/ + +abstract public class DNSSDException extends Exception +{ + public static final int NO_ERROR = 0; + public static final int UNKNOWN = -65537; + public static final int NO_SUCH_NAME = -65538; + public static final int NO_MEMORY = -65539; + public static final int BAD_PARAM = -65540; + public static final int BAD_REFERENCE = -65541; + public static final int BAD_STATE = -65542; + public static final int BAD_FLAGS = -65543; + public static final int UNSUPPORTED = -65544; + public static final int NOT_INITIALIZED = -65545; + public static final int ALREADY_REGISTERED = -65547; + public static final int NAME_CONFLICT = -65548; + public static final int INVALID = -65549; + public static final int INCOMPATIBLE = -65551; + public static final int BAD_INTERFACE_INDEX = -65552; + + /** Returns the sub-code that identifies the particular error. */ + abstract public int getErrorCode(); +} + diff --git a/mDNSShared/Java/DNSSDRegistration.java b/mDNSShared/Java/DNSSDRegistration.java new file mode 100644 index 0000000..4a4942f --- /dev/null +++ b/mDNSShared/Java/DNSSDRegistration.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: DNSSDRegistration.java,v $ +Revision 1.2 2004/12/11 03:01:00 rpantos + Java DNSRecord API should be cleaned up + +Revision 1.1 2004/04/30 16:32:34 rpantos +First checked in. + + + This file declares the public interface to DNSSDRegistration, a DNSSDService + subclass that allows a client to control a service registration. + */ + + +package com.apple.dnssd; + + +/** A tracking object for a registration created by {@link DNSSD#register}. */ + +public interface DNSSDRegistration extends DNSSDService +{ + /** Get a reference to the primary TXT record of a registered service.

+ The record can be updated by sending it an update() message.

+ +

+ @return A {@link DNSRecord}. + If {@link DNSSDRegistration#stop} is called, the DNSRecord is also + invalidated and may not be used further. + */ + DNSRecord getTXTRecord() + throws DNSSDException; + + /** Add a record to a registered service.

+ The name of the record will be the same as the registered service's name.

+ The record can be updated or deregistered by sending it an update() or remove() message.

+ + @param flags + Currently unused, reserved for future use. +

+ @param rrType + The type of the record (e.g. TXT, SRV, etc), as defined in nameser.h. +

+ @param rData + The raw rdata to be contained in the added resource record. +

+ @param ttl + The time to live of the resource record, in seconds. +

+ @return A {@link DNSRecord} that may be passed to updateRecord() or removeRecord(). + If {@link DNSSDRegistration#stop} is called, the DNSRecord is also + invalidated and may not be used further. + */ + DNSRecord addRecord( int flags, int rrType, byte[] rData, int ttl) + throws DNSSDException; +} + diff --git a/mDNSShared/Java/DNSSDService.java b/mDNSShared/Java/DNSSDService.java new file mode 100644 index 0000000..9868372 --- /dev/null +++ b/mDNSShared/Java/DNSSDService.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: DNSSDService.java,v $ +Revision 1.2 2004/04/30 21:48:27 rpantos +Change line endings for CVS. + +Revision 1.1 2004/04/30 16:32:34 rpantos +First checked in. + + */ + + +package com.apple.dnssd; + +/** A tracking object for a service created by {@link DNSSD}. */ + +public interface DNSSDService +{ + /** + Halt the active operation and free resources associated with the DNSSDService.

+ + Any services or records registered with this DNSSDService will be deregistered. Any + Browse, Resolve, or Query operations associated with this reference will be terminated.

+ + Note: if the service was initialized with DNSSD.register(), and an extra resource record was + added to the service via {@link DNSSDRegistration#addRecord}, the DNSRecord so created + is invalidated when this method is called - the DNSRecord may not be used afterward. + */ + void stop(); +} + diff --git a/mDNSShared/Java/DomainListener.java b/mDNSShared/Java/DomainListener.java new file mode 100644 index 0000000..bfb319a --- /dev/null +++ b/mDNSShared/Java/DomainListener.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: DomainListener.java,v $ +Revision 1.2 2004/04/30 21:48:27 rpantos +Change line endings for CVS. + +Revision 1.1 2004/04/30 16:29:35 rpantos +First checked in. + + */ + + +package com.apple.dnssd; + + +/** + A listener that receives results from {@link DNSSD#enumerateDomains}. +*/ + +public interface DomainListener extends BaseListener +{ + /** Called to report discovered domains.

+ + @param domainEnum + The active domain enumerator. + @param flags + Possible values are: DNSSD.MORE_COMING, DNSSD.DEFAULT +

+ @param ifIndex + Specifies the interface on which the domain exists. (The index for a given + interface is determined via the if_nametoindex() family of calls.) +

+ @param domain + The name of the domain. + */ + void domainFound( DNSSDService domainEnum, int flags, int ifIndex, String domain); + + /** Called to report that a domain has disappeared.

+ + @param domainEnum + The active domain enumerator. + @param flags + Possible values are: DNSSD.MORE_COMING, DNSSD.DEFAULT +

+ @param ifIndex + Specifies the interface on which the domain exists. (The index for a given + interface is determined via the if_nametoindex() family of calls.) +

+ @param domain + The name of the domain. + */ + void domainLost( DNSSDService domainEnum, int flags, int ifIndex, String domain); +} + diff --git a/mDNSShared/Java/JNISupport.c b/mDNSShared/Java/JNISupport.c new file mode 100644 index 0000000..ef9940a --- /dev/null +++ b/mDNSShared/Java/JNISupport.c @@ -0,0 +1,942 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: JNISupport.c,v $ +Revision 1.9 2004/12/11 03:01:00 rpantos + Java DNSRecord API should be cleaned up + +Revision 1.8 2004/11/30 23:51:05 cheshire +Remove double semicolons + +Revision 1.7 2004/11/23 08:12:04 shersche +Implement if_nametoindex and if_indextoname for Win32 platforms + +Revision 1.6 2004/11/23 03:41:14 cheshire +Change JNISupport.c to call if_indextoname & if_nametoindex directly. +(May require some additional glue code to work on Windows.) + +Revision 1.5 2004/11/17 17:07:44 cheshire +Updated comment about AUTO_CALLBACKS + +Revision 1.4 2004/11/12 03:23:09 rpantos +rdar://problem/3809541 implement getIfIndexForName, getNameForIfIndex. + +Revision 1.3 2004/06/18 04:44:17 rpantos +Adapt to API unification on Windows + +Revision 1.2 2004/05/28 23:34:42 ksekar +: Java project build errors + +Revision 1.1 2004/04/30 16:29:35 rpantos +First checked in. + + + This file contains the platform support for DNSSD and related Java classes. + It is used to shim through to the underlying API. + */ + +// AUTO_CALLBACKS should be set to 1 if the underlying mDNS implementation fires response +// callbacks automatically (as in the early Windows prototypes). +// AUTO_CALLBACKS should be set to 0 if the client must call DNSServiceProcessResult() to +// invoke response callbacks (as is true on Mac OS X, Posix, Windows, etc.). +// (Invoking callbacks automatically on a different thread sounds attractive, but while +// the client gains by not needing to add an event source to its main event loop, it loses +// by being forced to deal with concurrency and locking, which can be a bigger burden.) +#ifndef AUTO_CALLBACKS +#define AUTO_CALLBACKS 0 +#endif + +#if !AUTO_CALLBACKS +#ifdef _WIN32 +#include +#else //_WIN32 +#include +#include +#endif // _WIN32 +#endif // AUTO_CALLBACKS + +#include + +#include +#include +#include +#ifdef _WIN32 +#include +#include +static char * if_indextoname( DWORD ifIndex, char * nameBuff); +static DWORD if_nametoindex( const char * nameStr ); +#define IF_NAMESIZE MAX_ADAPTER_NAME_LENGTH +#else // _WIN32 +#include +#include +#endif // _WIN32 +#include + +#include "DNSSD.java.h" + +// convenience definition +#ifdef __GNUC__ +#define _UNUSED __attribute__ ((unused)) +#else +#define _UNUSED +#endif + +enum { + kInterfaceVersion = 1 // Must match version in .jar file +}; + +typedef struct OpContext OpContext; + +struct OpContext +{ + DNSServiceRef ServiceRef; + JNIEnv *Env; + jobject JavaObj; + jobject ClientObj; + jmethodID Callback; + jmethodID Callback2; +}; + +// For AUTO_CALLBACKS, we must attach the callback thread to the Java VM prior to upcall. +#if AUTO_CALLBACKS +JavaVM *gJavaVM = NULL; +#endif + + +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_InitLibrary( JNIEnv *pEnv, jclass cls, + jint callerVersion) +{ + /* Ensure that caller & interface versions match. */ + if ( callerVersion != kInterfaceVersion) + return kDNSServiceErr_Incompatible; + +#if AUTO_CALLBACKS + { + jsize numVMs; + + if ( 0 != JNI_GetCreatedJavaVMs( &gJavaVM, 1, &numVMs)) + return kDNSServiceErr_BadState; + } +#endif + + // Set AppleDNSSD.hasAutoCallbacks + { +#if AUTO_CALLBACKS + jboolean hasAutoC = JNI_TRUE; +#else + jboolean hasAutoC = JNI_FALSE; +#endif + jfieldID hasAutoCField = (*pEnv)->GetStaticFieldID( pEnv, cls, "hasAutoCallbacks", "Z"); + (*pEnv)->SetStaticBooleanField( pEnv, cls, hasAutoCField, hasAutoC); + } + + return kDNSServiceErr_NoError; +} + + +static const char* SafeGetUTFChars( JNIEnv *pEnv, jstring str) +// Wrapper for JNI GetStringUTFChars() that returns NULL for null str. +{ + return str != NULL ? (*pEnv)->GetStringUTFChars( pEnv, str, 0) : NULL; +} + +static void SafeReleaseUTFChars( JNIEnv *pEnv, jstring str, const char *buff) +// Wrapper for JNI GetStringUTFChars() that handles null str. +{ + if ( str != NULL) + (*pEnv)->ReleaseStringUTFChars( pEnv, str, buff); +} + + +#if AUTO_CALLBACKS +static void SetupCallbackState( JNIEnv **ppEnv) +{ + (*gJavaVM)->AttachCurrentThread( gJavaVM, (void**) ppEnv, NULL); +} + +static void TeardownCallbackState( void ) +{ + (*gJavaVM)->DetachCurrentThread( gJavaVM); +} + +#else // AUTO_CALLBACKS + +static void SetupCallbackState( JNIEnv **ppEnv _UNUSED) +{ + // No setup necessary if ProcessResults() has been called +} + +static void TeardownCallbackState( void ) +{ + // No teardown necessary if ProcessResults() has been called +} +#endif // AUTO_CALLBACKS + + +static OpContext *NewContext( JNIEnv *pEnv, jobject owner, const char *ownerClass, + const char *callbackName, const char *callbackSig) +// Create and initialize a new OpContext. +{ + OpContext *pContext = (OpContext*) malloc( sizeof *pContext); + + if ( pContext != NULL) + { + jfieldID clientField = (*pEnv)->GetFieldID( pEnv, (*pEnv)->GetObjectClass( pEnv, owner), + "fClient", ownerClass); + + pContext->JavaObj = (*pEnv)->NewWeakGlobalRef( pEnv, owner); // must convert local ref to global to cache; + pContext->ClientObj = (*pEnv)->GetObjectField( pEnv, owner, clientField); + pContext->ClientObj = (*pEnv)->NewWeakGlobalRef( pEnv, pContext->ClientObj); // must convert local ref to global to cache + pContext->Callback = (*pEnv)->GetMethodID( pEnv, + (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj), + callbackName, callbackSig); + pContext->Callback2 = NULL; // not always used + } + + return pContext; +} + + +static void ReportError( JNIEnv *pEnv, jobject target, jobject service, DNSServiceErrorType err) +// Invoke operationFailed() method on target with err. +{ + jclass cls = (*pEnv)->GetObjectClass( pEnv, target); + jmethodID opFailed = (*pEnv)->GetMethodID( pEnv, cls, "operationFailed", + "(Lcom/apple/dnssd/DNSSDService;I)V"); + + (*pEnv)->CallVoidMethod( pEnv, target, opFailed, service, err); +} + +JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleService_HaltOperation( JNIEnv *pEnv, jobject pThis) +/* Deallocate the dns_sd service browser and set the Java object's fNativeContext field to 0. */ +{ + jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); + jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I"); + + if ( contextField != 0) + { + OpContext *pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField); + if ( pContext != NULL) + { + (*pEnv)->SetIntField( pEnv, pThis, contextField, 0); + if ( pContext->ServiceRef != NULL) + DNSServiceRefDeallocate( pContext->ServiceRef); + + (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->JavaObj); + (*pEnv)->DeleteWeakGlobalRef( pEnv, pContext->ClientObj); + free( pContext); + } + } +} + + +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleService_BlockForData( JNIEnv *pEnv, jobject pThis, jint msTimeout) +/* Block for timeout ms (or forever if -1). Returns 1 if data present, 0 if timed out, -1 if not browsing. */ +{ +#if AUTO_CALLBACKS + return -1; // BlockForData() not supported with AUTO_CALLBACKS +#else // AUTO_CALLBACKS + jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); + jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I"); + jint rc = -1; + + if ( contextField != 0) + { + OpContext *pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField); + if ( pContext != NULL) + { + fd_set readFDs; + int sd = DNSServiceRefSockFD( pContext->ServiceRef); + struct timeval timeout = { msTimeout / 1000, 10 * (msTimeout % 1000) }; + struct timeval *pTimeout = msTimeout == -1 ? NULL : &timeout; + + FD_ZERO( &readFDs); + FD_SET( sd, &readFDs); + + rc = select( sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, pTimeout); + } + } + + return rc; +#endif // AUTO_CALLBACKS +} + + +JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleService_ProcessResults( JNIEnv *pEnv, jobject pThis) +/* Call through to DNSServiceProcessResult() while data remains on socket. */ +{ +#if !AUTO_CALLBACKS // ProcessResults() not supported with AUTO_CALLBACKS + + jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); + jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I"); + OpContext *pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField); + + if ( pContext != NULL) + { + int sd = DNSServiceRefSockFD( pContext->ServiceRef); + fd_set readFDs; + struct timeval zeroTimeout = { 0, 0 }; + + pContext->Env = pEnv; + + FD_ZERO( &readFDs); + FD_SET( sd, &readFDs); + + while ( 0 < select( sd + 1, &readFDs, (fd_set*) NULL, (fd_set*) NULL, &zeroTimeout)) + { + DNSServiceProcessResult( pContext->ServiceRef); + } + } +#endif // AUTO_CALLBACKS +} + + +static void DNSSD_API ServiceBrowseReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, + const char *replyDomain, void *context) +{ + OpContext *pContext = (OpContext*) context; + + SetupCallbackState( &pContext->Env); + + if ( pContext->ClientObj != NULL && pContext->Callback != NULL) + { + if ( errorCode == kDNSServiceErr_NoError) + { + (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, + ( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2, + pContext->JavaObj, flags, interfaceIndex, + (*pContext->Env)->NewStringUTF( pContext->Env, serviceName), + (*pContext->Env)->NewStringUTF( pContext->Env, regtype), + (*pContext->Env)->NewStringUTF( pContext->Env, replyDomain)); + } + else + ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode); + } + + TeardownCallbackState(); +} + +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleBrowser_CreateBrowser( JNIEnv *pEnv, jobject pThis, + jint flags, jint ifIndex, jstring regType, jstring domain) +{ + jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); + jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I"); + OpContext *pContext = NULL; + DNSServiceErrorType err = kDNSServiceErr_NoError; + + if ( contextField != 0) + pContext = NewContext( pEnv, pThis, "Lcom/apple/dnssd/BrowseListener;", "serviceFound", + "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + else + err = kDNSServiceErr_BadParam; + + if ( pContext != NULL) + { + const char *regStr = SafeGetUTFChars( pEnv, regType); + const char *domainStr = SafeGetUTFChars( pEnv, domain); + + pContext->Callback2 = (*pEnv)->GetMethodID( pEnv, + (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj), + "serviceLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + + err = DNSServiceBrowse( &pContext->ServiceRef, flags, ifIndex, regStr, domainStr, ServiceBrowseReply, pContext); + if ( err == kDNSServiceErr_NoError) + { + (*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext); + } + + SafeReleaseUTFChars( pEnv, regType, regStr); + SafeReleaseUTFChars( pEnv, domain, domainStr); + } + else + err = kDNSServiceErr_NoMemory; + + return err; +} + + +static void DNSSD_API ServiceResolveReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, + uint16_t port, uint16_t txtLen, const char *txtRecord, void *context) +{ + OpContext *pContext = (OpContext*) context; + jclass txtCls; + jmethodID txtCtor; + jbyteArray txtBytes; + jobject txtObj; + jbyte *pBytes; + + SetupCallbackState( &pContext->Env); + + txtCls = (*pContext->Env)->FindClass( pContext->Env, "com/apple/dnssd/TXTRecord"); + txtCtor = (*pContext->Env)->GetMethodID( pContext->Env, txtCls, "", "([B)V"); + + if ( pContext->ClientObj != NULL && pContext->Callback != NULL && txtCtor != NULL && + NULL != ( txtBytes = (*pContext->Env)->NewByteArray( pContext->Env, txtLen))) + { + if ( errorCode == kDNSServiceErr_NoError) + { + // Since Java ints are defined to be big-endian, we canonicalize 'port' from a 16-bit + // pattern into a number here. + port = ( ((unsigned char*) &port)[0] << 8) | ((unsigned char*) &port)[1]; + + // Initialize txtBytes with contents of txtRecord + pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, txtBytes, NULL); + memcpy( pBytes, txtRecord, txtLen); + (*pContext->Env)->ReleaseByteArrayElements( pContext->Env, txtBytes, pBytes, JNI_COMMIT); + + // Construct txtObj with txtBytes + txtObj = (*pContext->Env)->NewObject( pContext->Env, txtCls, txtCtor, txtBytes); + (*pContext->Env)->DeleteLocalRef( pContext->Env, txtBytes); + + (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback, + pContext->JavaObj, flags, interfaceIndex, + (*pContext->Env)->NewStringUTF( pContext->Env, fullname), + (*pContext->Env)->NewStringUTF( pContext->Env, hosttarget), + port, txtObj); + } + else + ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode); + } + + TeardownCallbackState(); +} + +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleResolver_CreateResolver( JNIEnv *pEnv, jobject pThis, + jint flags, jint ifIndex, jstring serviceName, jstring regType, jstring domain) +{ + jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); + jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I"); + OpContext *pContext = NULL; + DNSServiceErrorType err = kDNSServiceErr_NoError; + + if ( contextField != 0) + pContext = NewContext( pEnv, pThis, "Lcom/apple/dnssd/ResolveListener;", "serviceResolved", + "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;Ljava/lang/String;ILcom/apple/dnssd/TXTRecord;)V"); + else + err = kDNSServiceErr_BadParam; + + if ( pContext != NULL) + { + const char *servStr = SafeGetUTFChars( pEnv, serviceName); + const char *regStr = SafeGetUTFChars( pEnv, regType); + const char *domainStr = SafeGetUTFChars( pEnv, domain); + + err = DNSServiceResolve( &pContext->ServiceRef, flags, ifIndex, + servStr, regStr, domainStr, ServiceResolveReply, pContext); + if ( err == kDNSServiceErr_NoError) + { + (*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext); + } + + SafeReleaseUTFChars( pEnv, serviceName, servStr); + SafeReleaseUTFChars( pEnv, regType, regStr); + SafeReleaseUTFChars( pEnv, domain, domainStr); + } + else + err = kDNSServiceErr_NoMemory; + + return err; +} + + +static void DNSSD_API ServiceRegisterReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, + DNSServiceErrorType errorCode, const char *fullname, + const char *regType, const char *domain, void *context) +{ + OpContext *pContext = (OpContext*) context; + + SetupCallbackState( &pContext->Env); + + if ( pContext->ClientObj != NULL && pContext->Callback != NULL) + { + if ( errorCode == kDNSServiceErr_NoError) + { + (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback, + pContext->JavaObj, flags, + (*pContext->Env)->NewStringUTF( pContext->Env, fullname), + (*pContext->Env)->NewStringUTF( pContext->Env, regType), + (*pContext->Env)->NewStringUTF( pContext->Env, domain)); + } + else + ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode); + } + TeardownCallbackState(); +} + +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_BeginRegister( JNIEnv *pEnv, jobject pThis, + jint ifIndex, jint flags, jstring serviceName, jstring regType, + jstring domain, jstring host, jint port, jbyteArray txtRecord) +{ + jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); + jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I"); + OpContext *pContext = NULL; + DNSServiceErrorType err = kDNSServiceErr_NoError; + jbyte *pBytes; + jsize numBytes; + + if ( contextField != 0) + pContext = NewContext( pEnv, pThis, "Lcom/apple/dnssd/RegisterListener;", "serviceRegistered", + "(Lcom/apple/dnssd/DNSSDRegistration;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + else + err = kDNSServiceErr_BadParam; + + if ( pContext != NULL) + { + const char *servStr = SafeGetUTFChars( pEnv, serviceName); + const char *regStr = SafeGetUTFChars( pEnv, regType); + const char *domainStr = SafeGetUTFChars( pEnv, domain); + const char *hostStr = SafeGetUTFChars( pEnv, host); + + // Since Java ints are defined to be big-endian, we de-canonicalize 'port' from a + // big-endian number into a 16-bit pattern here. + uint16_t portBits = port; + portBits = ( ((unsigned char*) &portBits)[0] << 8) | ((unsigned char*) &portBits)[1]; + + pBytes = txtRecord ? (*pEnv)->GetByteArrayElements( pEnv, txtRecord, NULL) : NULL; + numBytes = txtRecord ? (*pEnv)->GetArrayLength( pEnv, txtRecord) : 0; + + err = DNSServiceRegister( &pContext->ServiceRef, flags, ifIndex, servStr, regStr, + domainStr, hostStr, portBits, + numBytes, pBytes, ServiceRegisterReply, pContext); + if ( err == kDNSServiceErr_NoError) + { + (*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext); + } + + if ( pBytes != NULL) + (*pEnv)->ReleaseByteArrayElements( pEnv, txtRecord, pBytes, 0); + + SafeReleaseUTFChars( pEnv, serviceName, servStr); + SafeReleaseUTFChars( pEnv, regType, regStr); + SafeReleaseUTFChars( pEnv, domain, domainStr); + SafeReleaseUTFChars( pEnv, host, hostStr); + } + else + err = kDNSServiceErr_NoMemory; + + return err; +} + +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleRegistration_AddRecord( JNIEnv *pEnv, jobject pThis, + jint flags, jint rrType, jbyteArray rData, jint ttl, jobject destObj) +{ + jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); + jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I"); + jclass destCls = (*pEnv)->GetObjectClass( pEnv, destObj); + jfieldID recField = (*pEnv)->GetFieldID( pEnv, destCls, "fRecord", "I"); + OpContext *pContext = NULL; + DNSServiceErrorType err = kDNSServiceErr_NoError; + jbyte *pBytes; + jsize numBytes; + DNSRecordRef recRef; + + if ( contextField != 0) + pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, pThis, contextField); + if ( pContext == NULL || pContext->ServiceRef == NULL) + return kDNSServiceErr_BadParam; + + pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL); + numBytes = (*pEnv)->GetArrayLength( pEnv, rData); + + err = DNSServiceAddRecord( pContext->ServiceRef, &recRef, flags, rrType, numBytes, pBytes, ttl); + if ( err == kDNSServiceErr_NoError) + { + (*pEnv)->SetIntField( pEnv, destObj, recField, (jint) recRef); + } + + if ( pBytes != NULL) + (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0); + + return err; +} + +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Update( JNIEnv *pEnv, jobject pThis, + jint flags, jbyteArray rData, jint ttl) +{ + jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); + jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;"); + jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "I"); + OpContext *pContext = NULL; + DNSServiceErrorType err = kDNSServiceErr_NoError; + jbyte *pBytes; + jsize numBytes; + DNSRecordRef recRef = NULL; + + if ( ownerField != 0) + { + jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField); + jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj); + jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "I"); + if ( contextField != 0) + pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, ownerObj, contextField); + } + if ( recField != 0) + recRef = (DNSRecordRef) (*pEnv)->GetIntField( pEnv, pThis, recField); + if ( pContext == NULL || pContext->ServiceRef == NULL) + return kDNSServiceErr_BadParam; + + pBytes = (*pEnv)->GetByteArrayElements( pEnv, rData, NULL); + numBytes = (*pEnv)->GetArrayLength( pEnv, rData); + + err = DNSServiceUpdateRecord( pContext->ServiceRef, recRef, flags, numBytes, pBytes, ttl); + + if ( pBytes != NULL) + (*pEnv)->ReleaseByteArrayElements( pEnv, rData, pBytes, 0); + + return err; +} + +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSRecord_Remove( JNIEnv *pEnv, jobject pThis) +{ + jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); + jfieldID ownerField = (*pEnv)->GetFieldID( pEnv, cls, "fOwner", "Lcom/apple/dnssd/AppleService;"); + jfieldID recField = (*pEnv)->GetFieldID( pEnv, cls, "fRecord", "I"); + OpContext *pContext = NULL; + DNSServiceErrorType err = kDNSServiceErr_NoError; + DNSRecordRef recRef = NULL; + + if ( ownerField != 0) + { + jobject ownerObj = (*pEnv)->GetObjectField( pEnv, pThis, ownerField); + jclass ownerClass = (*pEnv)->GetObjectClass( pEnv, ownerObj); + jfieldID contextField = (*pEnv)->GetFieldID( pEnv, ownerClass, "fNativeContext", "I"); + if ( contextField != 0) + pContext = (OpContext*) (*pEnv)->GetIntField( pEnv, ownerObj, contextField); + } + if ( recField != 0) + recRef = (DNSRecordRef) (*pEnv)->GetIntField( pEnv, pThis, recField); + if ( pContext == NULL || pContext->ServiceRef == NULL) + return kDNSServiceErr_BadParam; + + err = DNSServiceRemoveRecord( pContext->ServiceRef, recRef, 0); + + return err; +} + + +static void DNSSD_API ServiceQueryReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *serviceName, + uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, + const void *rdata, uint32_t ttl, void *context) +{ + OpContext *pContext = (OpContext*) context; + jbyteArray rDataObj; + jbyte *pBytes; + + SetupCallbackState( &pContext->Env); + + if ( pContext->ClientObj != NULL && pContext->Callback != NULL && + NULL != ( rDataObj = (*pContext->Env)->NewByteArray( pContext->Env, rdlen))) + { + if ( errorCode == kDNSServiceErr_NoError) + { + // Initialize rDataObj with contents of rdata + pBytes = (*pContext->Env)->GetByteArrayElements( pContext->Env, rDataObj, NULL); + memcpy( pBytes, rdata, rdlen); + (*pContext->Env)->ReleaseByteArrayElements( pContext->Env, rDataObj, pBytes, JNI_COMMIT); + + (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, pContext->Callback, + pContext->JavaObj, flags, interfaceIndex, + (*pContext->Env)->NewStringUTF( pContext->Env, serviceName), + rrtype, rrclass, rDataObj, ttl); + } + else + ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode); + } + TeardownCallbackState(); +} + +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleQuery_CreateQuery( JNIEnv *pEnv, jobject pThis, + jint flags, jint ifIndex, jstring serviceName, jint rrtype, jint rrclass) +{ + jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); + jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I"); + OpContext *pContext = NULL; + DNSServiceErrorType err = kDNSServiceErr_NoError; + + if ( contextField != 0) + pContext = NewContext( pEnv, pThis, "Lcom/apple/dnssd/QueryListener;", "queryAnswered", + "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;II[BI)V"); + else + err = kDNSServiceErr_BadParam; + + if ( pContext != NULL) + { + const char *servStr = SafeGetUTFChars( pEnv, serviceName); + + err = DNSServiceQueryRecord( &pContext->ServiceRef, flags, ifIndex, servStr, + rrtype, rrclass, ServiceQueryReply, pContext); + if ( err == kDNSServiceErr_NoError) + { + (*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext); + } + + SafeReleaseUTFChars( pEnv, serviceName, servStr); + } + else + err = kDNSServiceErr_NoMemory; + + return err; +} + + +static void DNSSD_API DomainEnumReply( DNSServiceRef sdRef _UNUSED, DNSServiceFlags flags, uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *replyDomain, void *context) +{ + OpContext *pContext = (OpContext*) context; + + SetupCallbackState( &pContext->Env); + + if ( pContext->ClientObj != NULL && pContext->Callback != NULL) + { + if ( errorCode == kDNSServiceErr_NoError) + { + (*pContext->Env)->CallVoidMethod( pContext->Env, pContext->ClientObj, + ( flags & kDNSServiceFlagsAdd) != 0 ? pContext->Callback : pContext->Callback2, + pContext->JavaObj, flags, interfaceIndex, + (*pContext->Env)->NewStringUTF( pContext->Env, replyDomain)); + } + else + ReportError( pContext->Env, pContext->ClientObj, pContext->JavaObj, errorCode); + } + TeardownCallbackState(); +} + +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDomainEnum_BeginEnum( JNIEnv *pEnv, jobject pThis, + jint flags, jint ifIndex) +{ + jclass cls = (*pEnv)->GetObjectClass( pEnv, pThis); + jfieldID contextField = (*pEnv)->GetFieldID( pEnv, cls, "fNativeContext", "I"); + OpContext *pContext = NULL; + DNSServiceErrorType err = kDNSServiceErr_NoError; + + if ( contextField != 0) + pContext = NewContext( pEnv, pThis, "Lcom/apple/dnssd/DomainListener;", "domainFound", + "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V"); + else + err = kDNSServiceErr_BadParam; + + if ( pContext != NULL) + { + pContext->Callback2 = (*pEnv)->GetMethodID( pEnv, + (*pEnv)->GetObjectClass( pEnv, pContext->ClientObj), + "domainLost", "(Lcom/apple/dnssd/DNSSDService;IILjava/lang/String;)V"); + + err = DNSServiceEnumerateDomains( &pContext->ServiceRef, flags, ifIndex, + DomainEnumReply, pContext); + if ( err == kDNSServiceErr_NoError) + { + (*pEnv)->SetIntField( pEnv, pThis, contextField, (jint) pContext); + } + } + else + err = kDNSServiceErr_NoMemory; + + return err; +} + + +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_ConstructName( JNIEnv *pEnv, jobject pThis _UNUSED, + jstring serviceName, jstring regtype, jstring domain, jobjectArray pOut) +{ + DNSServiceErrorType err = kDNSServiceErr_NoError; + const char *nameStr = SafeGetUTFChars( pEnv, serviceName); + const char *regStr = SafeGetUTFChars( pEnv, regtype); + const char *domStr = SafeGetUTFChars( pEnv, domain); + char buff[ kDNSServiceMaxDomainName + 1]; + + err = DNSServiceConstructFullName( buff, nameStr, regStr, domStr); + + if ( err == kDNSServiceErr_NoError) + { + // pOut is expected to be a String[1] array. + (*pEnv)->SetObjectArrayElement( pEnv, pOut, 0, (*pEnv)->NewStringUTF( pEnv, buff)); + } + + SafeReleaseUTFChars( pEnv, serviceName, nameStr); + SafeReleaseUTFChars( pEnv, regtype, regStr); + SafeReleaseUTFChars( pEnv, domain, domStr); + + return err; +} + +JNIEXPORT void JNICALL Java_com_apple_dnssd_AppleDNSSD_ReconfirmRecord( JNIEnv *pEnv, jobject pThis _UNUSED, + jint flags, jint ifIndex, jstring fullName, + jint rrtype, jint rrclass, jbyteArray rdata) +{ + jbyte *pBytes; + jsize numBytes; + const char *nameStr = SafeGetUTFChars( pEnv, fullName); + + pBytes = (*pEnv)->GetByteArrayElements( pEnv, rdata, NULL); + numBytes = (*pEnv)->GetArrayLength( pEnv, rdata); + + DNSServiceReconfirmRecord( flags, ifIndex, nameStr, rrtype, rrclass, numBytes, pBytes); + + if ( pBytes != NULL) + (*pEnv)->ReleaseByteArrayElements( pEnv, rdata, pBytes, 0); + + SafeReleaseUTFChars( pEnv, fullName, nameStr); +} + +#define LOCAL_ONLY_NAME "loo" + +JNIEXPORT jstring JNICALL Java_com_apple_dnssd_AppleDNSSD_GetNameForIfIndex( JNIEnv *pEnv, jobject pThis _UNUSED, + jint ifIndex) +{ + char *p = LOCAL_ONLY_NAME, nameBuff[IF_NAMESIZE]; + + if (ifIndex != kDNSServiceInterfaceIndexLocalOnly) + p = if_indextoname( ifIndex, nameBuff ); + + return (*pEnv)->NewStringUTF( pEnv, p); +} + + +JNIEXPORT jint JNICALL Java_com_apple_dnssd_AppleDNSSD_GetIfIndexForName( JNIEnv *pEnv, jobject pThis _UNUSED, + jstring ifName) +{ + uint32_t ifIndex = kDNSServiceInterfaceIndexLocalOnly; + const char *nameStr = SafeGetUTFChars( pEnv, ifName); + + if (strcmp(nameStr, LOCAL_ONLY_NAME)) + ifIndex = if_nametoindex( nameStr); + + SafeReleaseUTFChars( pEnv, ifName, nameStr); + + return ifIndex; +} + + +#if defined(_WIN32) +static char* +if_indextoname( DWORD ifIndex, char * nameBuff) +{ + PIP_ADAPTER_INFO pAdapterInfo = NULL; + PIP_ADAPTER_INFO pAdapter = NULL; + DWORD dwRetVal = 0; + char * ifName = NULL; + ULONG ulOutBufLen = 0; + + if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW) + { + goto exit; + } + + pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen); + + if (pAdapterInfo == NULL) + { + goto exit; + } + + dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen ); + + if (dwRetVal != NO_ERROR) + { + goto exit; + } + + pAdapter = pAdapterInfo; + while (pAdapter) + { + if (pAdapter->Index == ifIndex) + { + // It would be better if we passed in the length of nameBuff to this + // function, so we would have absolute certainty that no buffer + // overflows would occur. Buffer overflows *shouldn't* occur because + // nameBuff is of size MAX_ADAPTER_NAME_LENGTH. + strcpy( nameBuff, pAdapter->AdapterName ); + ifName = nameBuff; + break; + } + + pAdapter = pAdapter->Next; + } + +exit: + + if (pAdapterInfo != NULL) + { + free( pAdapterInfo ); + pAdapterInfo = NULL; + } + + return ifName; +} + + +static DWORD +if_nametoindex( const char * nameStr ) +{ + PIP_ADAPTER_INFO pAdapterInfo = NULL; + PIP_ADAPTER_INFO pAdapter = NULL; + DWORD dwRetVal = 0; + DWORD ifIndex = 0; + ULONG ulOutBufLen = 0; + + if (GetAdaptersInfo( NULL, &ulOutBufLen) != ERROR_BUFFER_OVERFLOW) + { + goto exit; + } + + pAdapterInfo = (IP_ADAPTER_INFO *) malloc(ulOutBufLen); + + if (pAdapterInfo == NULL) + { + goto exit; + } + + dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen ); + + if (dwRetVal != NO_ERROR) + { + goto exit; + } + + pAdapter = pAdapterInfo; + while (pAdapter) + { + if (strcmp(pAdapter->AdapterName, nameStr) == 0) + { + ifIndex = pAdapter->Index; + break; + } + + pAdapter = pAdapter->Next; + } + +exit: + + if (pAdapterInfo != NULL) + { + free( pAdapterInfo ); + pAdapterInfo = NULL; + } + + return ifIndex; +} +#endif diff --git a/mDNSShared/Java/QueryListener.java b/mDNSShared/Java/QueryListener.java new file mode 100644 index 0000000..7ece74c --- /dev/null +++ b/mDNSShared/Java/QueryListener.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: QueryListener.java,v $ +Revision 1.2 2004/04/30 21:48:27 rpantos +Change line endings for CVS. + +Revision 1.1 2004/04/30 16:29:35 rpantos +First checked in. + + */ + + +package com.apple.dnssd; + + +/** A listener that receives results from {@link DNSSD#queryRecord}. */ + +public interface QueryListener extends BaseListener +{ + /** Called when a record query has been completed.

+ + @param query + The active query object. +

+ @param flags + Possible values are DNSSD.MORE_COMING. +

+ @param ifIndex + The interface on which the query was resolved. (The index for a given + interface is determined via the if_nametoindex() family of calls.) +

+ @param fullName + The resource record's full domain name. +

+ @param rrtype + The resource record's type (e.g. PTR, SRV, etc) as defined by RFC 1035 and its updates. +

+ @param rrclass + The class of the resource record, as defined by RFC 1035 and its updates. +

+ @param rdata + The raw rdata of the resource record. +

+ @param ttl + The resource record's time to live, in seconds. + */ + void queryAnswered( DNSSDService query, int flags, int ifIndex, String fullName, + int rrtype, int rrclass, byte[] rdata, int ttl); +} + diff --git a/mDNSShared/Java/RegisterListener.java b/mDNSShared/Java/RegisterListener.java new file mode 100644 index 0000000..a6cf331 --- /dev/null +++ b/mDNSShared/Java/RegisterListener.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: RegisterListener.java,v $ +Revision 1.2 2004/04/30 21:48:27 rpantos +Change line endings for CVS. + +Revision 1.1 2004/04/30 16:29:35 rpantos +First checked in. + + */ + + +package com.apple.dnssd; + + +/** A listener that receives results from {@link DNSSD#register}. */ + +public interface RegisterListener extends BaseListener +{ + /** Called when a registration has been completed.

+ + @param registration + The active registration. +

+ @param flags + Currently unused, reserved for future use. +

+ @param serviceName + The service name registered (if the application did not specify a name in + DNSSD.register(), this indicates what name was automatically chosen). +

+ @param regType + The type of service registered, as it was passed to DNSSD.register(). +

+ @param domain + The domain on which the service was registered. If the application did not + specify a domain in DNSSD.register(), this is the default domain + on which the service was registered. + */ + void serviceRegistered( DNSSDRegistration registration, int flags, String serviceName, + String regType, String domain); +} + diff --git a/mDNSShared/Java/ResolveListener.java b/mDNSShared/Java/ResolveListener.java new file mode 100644 index 0000000..0e21353 --- /dev/null +++ b/mDNSShared/Java/ResolveListener.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ResolveListener.java,v $ +Revision 1.2 2004/04/30 21:48:27 rpantos +Change line endings for CVS. + +Revision 1.1 2004/04/30 16:29:35 rpantos +First checked in. + +*/ + + +package com.apple.dnssd; + + +/** A listener that receives results from {@link DNSSD#resolve}. */ + +public interface ResolveListener extends BaseListener +{ + /** Called when a service has been resolved.

+ + @param resolver + The active resolver object. +

+ @param flags + Currently unused, reserved for future use. +

+ @param fullName + The full service domain name, in the form <servicename>.<protocol>.<domain>. + (Any literal dots (".") are escaped with a backslash ("\."), and literal + backslashes are escaped with a second backslash ("\\"), e.g. a web server + named "Dr. Pepper" would have the fullname "Dr\.\032Pepper._http._tcp.local."). + This is the appropriate format to pass to standard system DNS APIs such as + res_query(), or to the special-purpose functions included in this API that + take fullname parameters. +

+ @param hostName + The target hostname of the machine providing the service. This name can + be passed to functions like queryRecord() to look up the host's IP address. +

+ @param port + The port number on which connections are accepted for this service. +

+ @param txtRecord + The service's primary txt record. + */ + void serviceResolved( DNSSDService resolver, int flags, int ifIndex, String fullName, + String hostName, int port, TXTRecord txtRecord); +} + diff --git a/mDNSShared/Java/TXTRecord.java b/mDNSShared/Java/TXTRecord.java new file mode 100644 index 0000000..5eed93e --- /dev/null +++ b/mDNSShared/Java/TXTRecord.java @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: TXTRecord.java,v $ +Revision 1.5 2004/08/25 21:54:36 rpantos + Fix getValue() for values containing '='. + +Revision 1.4 2004/08/04 01:04:50 rpantos + Fix set(); add remove() & toString(). + +Revision 1.3 2004/07/13 21:24:25 rpantos +Fix for . + +Revision 1.2 2004/04/30 21:48:27 rpantos +Change line endings for CVS. + +Revision 1.1 2004/04/30 16:29:35 rpantos +First checked in. + + To do: + - implement remove() + - fix set() to replace existing values + */ + + +package com.apple.dnssd; + + +/** + Object used to construct and parse DNS-SD format TXT records. + For more info see DNS-Based Service Discovery, section 6. +*/ + +public class TXTRecord +{ + /* + DNS-SD specifies that a TXT record corresponding to an SRV record consist of + a packed array of bytes, each preceded by a length byte. Each string + is an attribute-value pair. + + The TXTRecord object stores the entire TXT data as a single byte array, traversing it + as need be to implement its various methods. + */ + + static final protected byte kAttrSep = '='; + + protected byte[] fBytes; + + /** Constructs a new, empty TXT record. */ + public TXTRecord() + { fBytes = new byte[0]; } + + /** Constructs a new TXT record from a byte array in the standard format. */ + public TXTRecord( byte[] initBytes) + { fBytes = (byte[]) initBytes.clone(); } + + /** Set a key/value pair in the TXT record. Setting an existing key will replace its value.

+ @param key + The key name. Must be ASCII, with no '=' characters. +

+ @param value + Value to be encoded into bytes using the default platform character set. + */ + public void set( String key, String value) + { + byte[] valBytes = (value != null) ? value.getBytes() : null; + this.set( key, valBytes); + } + + /** Set a key/value pair in the TXT record. Setting an existing key will replace its value.

+ @param key + The key name. Must be ASCII, with no '=' characters. +

+ @param value + Binary representation of the value. + */ + public void set( String key, byte[] value) + { + byte[] keyBytes; + int valLen = (value != null) ? value.length : 0; + + try { + keyBytes = key.getBytes( "US-ASCII"); + } + catch ( java.io.UnsupportedEncodingException uee) { + throw new IllegalArgumentException(); + } + + for ( int i=0; i < keyBytes.length; i++) + if ( keyBytes[i] == '=') + throw new IllegalArgumentException(); + + if ( keyBytes.length + valLen >= 255) + throw new ArrayIndexOutOfBoundsException(); + + int prevLoc = this.remove( key); + if ( prevLoc == -1) + prevLoc = this.size(); + + this.insert( keyBytes, value, prevLoc); + } + + protected void insert( byte[] keyBytes, byte[] value, int index) + // Insert a key-value pair at index + { + byte[] oldBytes = fBytes; + int valLen = (value != null) ? value.length : 0; + int insertion = 0; + byte newLen, avLen; + + // locate the insertion point + for ( int i=0; i < index && insertion < fBytes.length; i++) + insertion += fBytes[ insertion] + 1; + + avLen = (byte) ( keyBytes.length + valLen + (value != null ? 1 : 0)); + newLen = (byte) ( avLen + oldBytes.length + 1); + + fBytes = new byte[ newLen]; + System.arraycopy( oldBytes, 0, fBytes, 0, insertion); + int secondHalfLen = oldBytes.length - insertion; + System.arraycopy( oldBytes, insertion, fBytes, newLen - secondHalfLen, secondHalfLen); + fBytes[ insertion] = avLen; + System.arraycopy( keyBytes, 0, fBytes, insertion + 1, keyBytes.length); + if ( value != null) + { + fBytes[ insertion + 1 + keyBytes.length] = kAttrSep; + System.arraycopy( value, 0, fBytes, insertion + keyBytes.length + 2, valLen); + } + } + + /** Remove a key/value pair from the TXT record. Returns index it was at, or -1 if not found. */ + public int remove( String key) + { + int avStart = 0; + + for ( int i=0; avStart < fBytes.length; i++) + { + int avLen = fBytes[ avStart]; + if ( key.length() <= avLen && + ( key.length() == avLen || fBytes[ avStart + key.length() + 1] == kAttrSep)) + { + String s = new String( fBytes, avStart + 1, key.length()); + if ( 0 == key.compareToIgnoreCase( s)) + { + byte[] oldBytes = fBytes; + fBytes = new byte[ oldBytes.length - avLen - 1]; + System.arraycopy( oldBytes, 0, fBytes, 0, avStart); + System.arraycopy( oldBytes, avStart + avLen + 1, fBytes, avStart, oldBytes.length - avStart - avLen - 1); + return i; + } + } + avStart += avLen + 1; + } + return -1; + } + + /** Return the number of keys in the TXT record. */ + public int size() + { + int i, avStart; + + for ( i=0, avStart=0; avStart < fBytes.length; i++) + avStart += fBytes[ avStart] + 1; + return i; + } + + /** Return true if key is present in the TXT record, false if not. */ + public boolean contains( String key) + { + String s = null; + + for ( int i=0; null != ( s = this.getKey( i)); i++) + if ( 0 == key.compareToIgnoreCase( s)) + return true; + return false; + } + + /** Return a key in the TXT record by zero-based index. Returns null if index exceeds the total number of keys. */ + public String getKey( int index) + { + int avStart = 0; + + for ( int i=0; i < index && avStart < fBytes.length; i++) + avStart += fBytes[ avStart] + 1; + + if ( avStart < fBytes.length) + { + int avLen = fBytes[ avStart]; + int aLen = 0; + + for ( aLen=0; aLen < avLen; aLen++) + if ( fBytes[ avStart + aLen + 1] == kAttrSep) + break; + return new String( fBytes, avStart + 1, aLen); + } + return null; + } + + /** + Look up a key in the TXT record by zero-based index and return its value.

+ Returns null if index exceeds the total number of keys. + Returns null if the key is present with no value. + */ + public byte[] getValue( int index) + { + int avStart = 0; + byte[] value = null; + + for ( int i=0; i < index && avStart < fBytes.length; i++) + avStart += fBytes[ avStart] + 1; + + if ( avStart < fBytes.length) + { + int avLen = fBytes[ avStart]; + int aLen = 0; + + for ( aLen=0; aLen < avLen; aLen++) + { + if ( fBytes[ avStart + aLen + 1] == kAttrSep) + { + value = new byte[ avLen - aLen - 1]; + System.arraycopy( fBytes, avStart + aLen + 2, value, 0, avLen - aLen - 1); + break; + } + } + } + return value; + } + + /** Converts the result of getValue() to a string in the platform default character set. */ + public String getValueAsString( int index) + { + byte[] value = this.getValue( index); + return value != null ? new String( value) : null; + } + + /** Get the value associated with a key. Will be null if the key is not defined. + Array will have length 0 if the key is defined with an = but no value.

+ + @param forKey + The left-hand side of the key-value pair. +

+ @return The binary representation of the value. + */ + public byte[] getValue( String forKey) + { + String s = null; + int i; + + for ( i=0; null != ( s = this.getKey( i)); i++) + if ( 0 == forKey.compareToIgnoreCase( s)) + return this.getValue( i); + return null; + } + + /** Converts the result of getValue() to a string in the platform default character set.

+ + @param forKey + The left-hand side of the key-value pair. +

+ @return The value represented in the default platform character set. + */ + public String getValueAsString( String forKey) + { + byte[] val = this.getValue( forKey); + return val != null ? new String( val) : null; + } + + /** Return the contents of the TXT record as raw bytes. */ + public byte[] getRawBytes() { return (byte[]) fBytes.clone(); } + + /** Return a string representation of the object. */ + public String toString() + { + String a, result = null; + + for ( int i=0; null != ( a = this.getKey( i)); i++) + { + String av = String.valueOf( i) + "={" + a; + String val = this.getValueAsString( i); + if ( val != null) + av += "=" + val + "}"; + else + av += "}"; + if ( result == null) + result = av; + else + result = result + ", " + av; + } + return result != null ? result : ""; + } +} + diff --git a/mDNSShared/dns_sd.h b/mDNSShared/dns_sd.h index eaed335..4f22f67 100755 --- a/mDNSShared/dns_sd.h +++ b/mDNSShared/dns_sd.h @@ -1,42 +1,62 @@ /* - * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: dns_sd.h,v $ -Revision 1.3 2003/08/12 19:51:51 cheshire -Update to APSL 2.0 - - + * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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. */ #ifndef _DNS_SD_H #define _DNS_SD_H +#ifdef __cplusplus + extern "C" { +#endif + +/* standard calling convention under Win32 is __stdcall */ +#if defined(_WIN32) +#define DNSSD_API __stdcall +#else +#define DNSSD_API +#endif + +#if defined(__FreeBSD_version) && (__FreeBSD_version < 500000) +/* stdint.h does not exist on FreeBSD 4.x; its types are defined in sys/types.h instead */ #include -#include +#elif defined(__sun__) +#include +#elif defined(_WIN32) +#include +#define _UNUSED +#define bzero(a, b) memset(a, 0, b) +typedef UINT8 uint8_t; +typedef INT8 int8_t; +typedef UINT16 uint16_t; +typedef INT16 int16_t; +typedef UINT32 uint32_t; +typedef INT32 int32_t; +#else #include -#include - +#endif /* DNSServiceRef, DNSRecordRef * @@ -51,45 +71,136 @@ typedef struct _DNSRecordRef_t *DNSRecordRef; /* General flags used in functions defined below */ enum { - kDNSServiceFlagsMoreComing = 1, - kDNSServiceFlagsFinished = 0, /* i.e. bit not set */ - /* MoreComing indicates to a Browse callback that another result is - * queued. Applications should not update their UI to display browse - * results when the MoreComing flag is set, instead deferring the update - * until the callback's flag is Finished. */ - - kDNSServiceFlagsAdd = 2, - kDNSServiceFlagsDefault = 4, - kDNSServiceFlagsRemove = 0, /* i.e. bit not set */ - /* Flags for domain enumeration and browse reply callbacks. + kDNSServiceFlagsMoreComing = 0x1, + /* MoreComing indicates to a callback that at least one more result is + * queued and will be delivered following immediately after this one. + * Applications should not update their UI to display browse + * results when the MoreComing flag is set, because this would + * result in a great deal of ugly flickering on the screen. + * Applications should instead wait until until MoreComing is not set, + * and then update their UI. + * When MoreComing is not set, that doesn't mean there will be no more + * answers EVER, just that there are no more answers immediately + * available right now at this instant. If more answers become available + * in the future they will be delivered as usual. + */ + + kDNSServiceFlagsAdd = 0x2, + kDNSServiceFlagsDefault = 0x4, + /* Flags for domain enumeration and browse/query reply callbacks. * "Default" applies only to enumeration and is only valid in - * conjuction with "Add" + * conjuction with "Add". An enumeration callback with the "Add" + * flag NOT set indicates a "Remove", i.e. the domain is no longer + * valid. */ - kDNSServiceFlagsNoAutoRename = 8, - kDNSServiceFlagsAutoRename = 0, /* i.e. bit not set */ + kDNSServiceFlagsNoAutoRename = 0x8, /* Flag for specifying renaming behavior on name conflict when registering - * non-shared records. NoAutorename is only valid if a name is explicitly - * specified when registering a service (ie the default name is not used.) + * non-shared records. By default, name conflicts are automatically handled + * by renaming the service. NoAutoRename overrides this behavior - with this + * flag set, name conflicts will result in a callback. The NoAutorename flag + * is only valid if a name is explicitly specified when registering a service + * (i.e. the default name is not used.) */ - - kDNSServiceFlagsShared = 16, - kDNSServiceFlagsUnique = 32, + kDNSServiceFlagsShared = 0x10, + kDNSServiceFlagsUnique = 0x20, /* Flag for registering individual records on a connected - * DNSServiceRef. Shared indicates that there may be multiple records + * DNSServiceRef. Shared indicates that there may be multiple records * with this name on the network (e.g. PTR records). Unique indicates that the * record's name is to be unique on the network (e.g. SRV records). */ - kDNSServiceFlagsBrowseDomains = 64, - kDNSServiceFlagsRegistrationDomains = 128 + kDNSServiceFlagsBrowseDomains = 0x40, + kDNSServiceFlagsRegistrationDomains = 0x80, /* Flags for specifying domain enumeration type in DNSServiceEnumerateDomains. * BrowseDomains enumerates domains recommended for browsing, RegistrationDomains * enumerates domains recommended for registration. */ + + kDNSServiceFlagsLongLivedQuery = 0x100, + /* Flag for creating a long-lived unicast query for the DNSServiceQueryRecord call. */ + + kDNSServiceFlagsAllowRemoteQuery = 0x200, + /* Flag for creating a record for which we will answer remote queries + * (queries from hosts more than one hop away; hosts not directly connected to the local link). + */ + + kDNSServiceFlagsForceMulticast = 0x400 + /* Flag for signifying that a query or registration should be performed exclusively via multicast DNS, + * even for a name in a domain (e.g. foo.apple.com.) that would normally imply unicast DNS. + */ }; +/* + * The values for DNS Classes and Types are listed in RFC 1035, and are available + * on every OS in its DNS header file. Unfortunately every OS does not have the + * same header file containing DNS Class and Type constants, and the names of + * the constants are not consistent. For example, BIND 8 uses "T_A", + * BIND 9 uses "ns_t_a", Windows uses "DNS_TYPE_A", etc. + * For this reason, these constants are also listed here, so that code using + * the DNS-SD programming APIs can use these constants, so that the same code + * can compile on all our supported platforms. + */ + +enum + { + kDNSServiceClass_IN = 1 /* Internet */ + }; + +enum + { + kDNSServiceType_A = 1, /* Host address. */ + kDNSServiceType_NS = 2, /* Authoritative server. */ + kDNSServiceType_MD = 3, /* Mail destination. */ + kDNSServiceType_MF = 4, /* Mail forwarder. */ + kDNSServiceType_CNAME = 5, /* Canonical name. */ + kDNSServiceType_SOA = 6, /* Start of authority zone. */ + kDNSServiceType_MB = 7, /* Mailbox domain name. */ + kDNSServiceType_MG = 8, /* Mail group member. */ + kDNSServiceType_MR = 9, /* Mail rename name. */ + kDNSServiceType_NULL = 10, /* Null resource record. */ + kDNSServiceType_WKS = 11, /* Well known service. */ + kDNSServiceType_PTR = 12, /* Domain name pointer. */ + kDNSServiceType_HINFO = 13, /* Host information. */ + kDNSServiceType_MINFO = 14, /* Mailbox information. */ + kDNSServiceType_MX = 15, /* Mail routing information. */ + kDNSServiceType_TXT = 16, /* Text strings. */ + kDNSServiceType_RP = 17, /* Responsible person. */ + kDNSServiceType_AFSDB = 18, /* AFS cell database. */ + kDNSServiceType_X25 = 19, /* X_25 calling address. */ + kDNSServiceType_ISDN = 20, /* ISDN calling address. */ + kDNSServiceType_RT = 21, /* Router. */ + kDNSServiceType_NSAP = 22, /* NSAP address. */ + kDNSServiceType_NSAP_PTR = 23, /* Reverse NSAP lookup (deprecated). */ + kDNSServiceType_SIG = 24, /* Security signature. */ + kDNSServiceType_KEY = 25, /* Security key. */ + kDNSServiceType_PX = 26, /* X.400 mail mapping. */ + kDNSServiceType_GPOS = 27, /* Geographical position (withdrawn). */ + kDNSServiceType_AAAA = 28, /* Ip6 Address. */ + kDNSServiceType_LOC = 29, /* Location Information. */ + kDNSServiceType_NXT = 30, /* Next domain (security). */ + kDNSServiceType_EID = 31, /* Endpoint identifier. */ + kDNSServiceType_NIMLOC = 32, /* Nimrod Locator. */ + kDNSServiceType_SRV = 33, /* Server Selection. */ + kDNSServiceType_ATMA = 34, /* ATM Address */ + kDNSServiceType_NAPTR = 35, /* Naming Authority PoinTeR */ + kDNSServiceType_KX = 36, /* Key Exchange */ + kDNSServiceType_CERT = 37, /* Certification record */ + kDNSServiceType_A6 = 38, /* IPv6 address (deprecates AAAA) */ + kDNSServiceType_DNAME = 39, /* Non-terminal DNAME (for IPv6) */ + kDNSServiceType_SINK = 40, /* Kitchen sink (experimentatl) */ + kDNSServiceType_OPT = 41, /* EDNS0 option (meta-RR) */ + kDNSServiceType_TKEY = 249, /* Transaction key */ + kDNSServiceType_TSIG = 250, /* Transaction signature. */ + kDNSServiceType_IXFR = 251, /* Incremental zone transfer. */ + kDNSServiceType_AXFR = 252, /* Transfer zone of authority. */ + kDNSServiceType_MAILB = 253, /* Transfer mailbox records. */ + kDNSServiceType_MAILA = 254, /* Transfer mail agent records. */ + kDNSServiceType_ANY = 255 /* Wildcard match. */ + }; + + /* possible error code values */ enum { @@ -106,16 +217,105 @@ enum kDNSServiceErr_AlreadyRegistered = -65547, kDNSServiceErr_NameConflict = -65548, kDNSServiceErr_Invalid = -65549, + kDNSServiceErr_Firewall = -65550, kDNSServiceErr_Incompatible = -65551, /* client library incompatible with daemon */ - kDNSServiceErr_BadinterfaceIndex = -65552 + kDNSServiceErr_BadInterfaceIndex = -65552, + kDNSServiceErr_Refused = -65553, + kDNSServiceErr_NoSuchRecord = -65554, + kDNSServiceErr_NoAuth = -65555, + kDNSServiceErr_NoSuchKey = -65556, + kDNSServiceErr_NATTraversal = -65557, + kDNSServiceErr_DoubleNAT = -65558, + kDNSServiceErr_BadTime = -65559 /* mDNS Error codes are in the range * FFFE FF00 (-65792) to FFFE FFFF (-65537) */ }; - + /* Maximum length, in bytes, of a domain name represented as an escaped C-String */ +/* including the final trailing dot, and the C-String terminating NULL at the end */ + #define kDNSServiceMaxDomainName 1005 +/* + * Notes on DNS Name Escaping + * -- or -- + * "Why is kDNSServiceMaxDomainName 1005, when the maximum legal domain name is 255 bytes?" + * + * All strings used in DNS-SD are UTF-8 strings. + * With few exceptions, most are also escaped using standard DNS escaping rules: + * + * '\\' represents a single literal '\' in the name + * '\.' represents a single literal '.' in the name + * '\ddd', where ddd is a three-digit decimal value from 000 to 255, + * represents a single literal byte with that value. + * A bare unescaped '.' is a label separator, marking a boundary between domain and subdomain. + * + * The exceptions, that do not use escaping, are the routines where the full + * DNS name of a resource is broken, for convenience, into servicename/regtype/domain. + * In these routines, the "servicename" is NOT escaped. It does not need to be, since + * it is, by definition, just a single literal string. Any characters in that string + * represent exactly what they are. The "regtype" portion is, technically speaking, + * escaped, but since legal regtypes are only allowed to contain letters, digits, + * and hyphens, the issue is moot. The "domain" portion is also escaped, though + * most domains in use on the public Internet today, like regtypes, don't contain + * any characters that need to be escaped. As DNS-SD becomes more popular, rich-text + * domains for service discovery will become common, so software should be written + * to cope with domains with escaping. + * + * For most software, these issues are transparent. When browsing, the discovered + * servicenames should simply be displayed as-is. When resolving, the discovered + * servicename/regtype/domain are simply passed unchanged to DNSServiceResolve(). + * When a DNSServiceResolve() succeeds, the returned fullname is already in + * the correct format to pass to standard system DNS APIs such as res_query(). + * For converting from servicename/regtype/domain to a single properly-escaped + * full DNS name, the helper function DNSServiceConstructFullName() is provided. + * + * The following (highly contrived) example illustrates the escaping process. + * Suppose you have an service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp" + * in subdomain "4th. Floor" of subdomain "Building 2" of domain "apple.com." + * The full (escaped) DNS name of this service's SRV record would be: + * Dr\.\032Smith\\Dr\.\032Johnson._ftp._tcp.4th\.\032Floor.Building\0322.apple.com. + */ + + +/* + * Constants for specifying an interface index + * + * Specific interface indexes are identified via a 32-bit unsigned integer returned + * by the if_nametoindex() family of calls. + * + * If the client passes 0 for interface index, that means "do the right thing", + * which (at present) means, "if the name is in an mDNS local multicast domain + * (e.g. 'local.', '254.169.in-addr.arpa.', '0.8.E.F.ip6.arpa.') then multicast + * on all applicable interfaces, otherwise send via unicast to the appropriate + * DNS server." Normally, most clients will use 0 for interface index to + * automatically get the default sensible behaviour. + * + * If the client passes a positive interface index, then for multicast names that + * indicates to do the operation only on that one interface. For unicast names the + * interface index is ignored unless kDNSServiceFlagsForceMulticast is also set. + * + * If the client passes kDNSServiceInterfaceIndexLocalOnly when registering + * a service, then that service will be found *only* by other local clients + * on the same machine that are browsing using kDNSServiceInterfaceIndexLocalOnly + * or kDNSServiceInterfaceIndexAny. + * If a client has a 'private' service, accessible only to other processes + * running on the same machine, this allows the client to advertise that service + * in a way such that it does not inadvertently appear in service lists on + * all the other machines on the network. + * + * If the client passes kDNSServiceInterfaceIndexLocalOnly when browsing + * then it will find *all* records registered on that same local machine. + * Clients explicitly wishing to discover *only* LocalOnly services can + * accomplish this by inspecting the interfaceIndex of each service reported + * to their DNSServiceBrowseReply() callback function, and discarding those + * where the interface index is not kDNSServiceInterfaceIndexLocalOnly. + */ + +#define kDNSServiceInterfaceIndexAny 0 +#define kDNSServiceInterfaceIndexLocalOnly ( (uint32_t) -1 ) + typedef uint32_t DNSServiceFlags; typedef int32_t DNSServiceErrorType; @@ -131,11 +331,11 @@ typedef int32_t DNSServiceErrorType; /* DNSServiceRefSockFD() * * Access underlying Unix domain socket for an initialized DNSServiceRef. - * The DNS Service Discovery implmementation uses this socket to communicate between + * The DNS Service Discovery implmementation uses this socket to communicate between * the client and the mDNSResponder daemon. The application MUST NOT directly read from * or write to this socket. Access to the socket is provided so that it can be used as a - * run loop source, or in a select() loop: when data is available for reading on the socket, - * DNSServiceProcessResult() should be called, which will extract the daemon's reply from + * run loop source, or in a select() loop: when data is available for reading on the socket, + * DNSServiceProcessResult() should be called, which will extract the daemon's reply from * the socket, and pass it to the appropriate application callback. By using a run loop or * select(), results from the daemon can be processed asynchronously. Without using these * constructs, DNSServiceProcessResult() will block until the response from the daemon arrives. @@ -144,17 +344,18 @@ typedef int32_t DNSServiceErrorType; * socket buffer. * * sdRef: A DNSServiceRef initialized by any of the DNSService calls. - * - * return value: The DNSServiceRef's underlying socket descriptor, or -1 on + * + * return value: The DNSServiceRef's underlying socket descriptor, or -1 on * error. */ - -int DNSServiceRefSockFD(DNSServiceRef sdRef); + +int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef); + /* DNSServiceProcessResult() * * Read a reply from the daemon, calling the appropriate application callback. This call will - * block until the daemon's response is received. Use DNSServiceRefSockFD() in + * block until the daemon's response is received. Use DNSServiceRefSockFD() in * conjunction with a run loop or select() to determine the presence of a response from the * server before calling this function to process the reply without blocking. Call this function * at any point if it is acceptable to block until the daemon's response arrives. Note that the @@ -169,101 +370,121 @@ int DNSServiceRefSockFD(DNSServiceRef sdRef); * an error code indicating the specific failure that occurred. */ -DNSServiceErrorType DNSServiceProcessResult(DNSServiceRef sdRef); +DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef); + /* DNSServiceRefDeallocate() * * Terminate a connection with the daemon and free memory associated with the DNSServiceRef. * Any services or records registered with this DNSServiceRef will be deregistered. Any - * Browse, Resolve, or Query operations called with this reference will be terminated. If the - * reference's underlying socket is used in a run loop or select() call, it should be removed BEFORE - * DNSServiceRefDeallocate() is called, as this function closes the reference's socket. + * Browse, Resolve, or Query operations called with this reference will be terminated. + * + * Note: If the reference's underlying socket is used in a run loop or select() call, it should + * be removed BEFORE DNSServiceRefDeallocate() is called, as this function closes the reference's + * socket. + * + * Note: If the reference was initialized with DNSServiceCreateConnection(), any DNSRecordRefs + * created via this reference will be invalidated by this call - the resource records are + * deregistered, and their DNSRecordRefs may not be used in subsequent functions. Similarly, + * if the reference was initialized with DNSServiceRegister, and an extra resource record was + * added to the service via DNSServiceAddRecord(), the DNSRecordRef created by the Add() call + * is invalidated when this function is called - the DNSRecordRef may not be used in subsequent + * functions. * * Note: This call is to be used only with the DNSServiceRef defined by this API. It is - * not compatible with dns_service_discovery_ref objects defined in the legacy Mach-based + * not compatible with dns_service_discovery_ref objects defined in the legacy Mach-based * DNSServiceDiscovery.h API. * * sdRef: A DNSServiceRef initialized by any of the DNSService calls. * */ -void DNSServiceRefDeallocate(DNSServiceRef sdRef); +void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef); /********************************************************************************************* - * + * * Domain Enumeration * *********************************************************************************************/ /* DNSServiceEnumerateDomains() - * + * * Asynchronously enumerate domains available for browsing and registration. - * Currently, the only domain returned is "local.", but other domains will be returned in future. * * The enumeration MUST be cancelled via DNSServiceRefDeallocate() when no more domains * are to be found. * + * Note that the names returned are (like all of DNS-SD) UTF-8 strings, + * and are escaped using standard DNS escaping rules. + * (See "Notes on DNS Name Escaping" earlier in this file for more details.) + * A graphical browser displaying a hierarchical tree-structured view should cut + * the names at the bare dots to yield individual labels, then de-escape each + * label according to the escaping rules, and then display the resulting UTF-8 text. * * DNSServiceDomainEnumReply Callback Parameters: * * sdRef: The DNSServiceRef initialized by DNSServiceEnumerateDomains(). * * flags: Possible values are: - * 1 (MoreComing) - * 2 (Add/Remove) - * 4 (Add Default) + * kDNSServiceFlagsMoreComing + * kDNSServiceFlagsAdd + * kDNSServiceFlagsDefault * - * interfaceIndex: Specifies the interface on which the domain exists. (The index for a given - * interface is determined via the if_nametoindex() family of calls.) + * interfaceIndex: Specifies the interface on which the domain exists. (The index for a given + * interface is determined via the if_nametoindex() family of calls.) * - * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise indicates + * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise indicates * the failure that occurred (other parameters are undefined if errorCode is nonzero). * * replyDomain: The name of the domain. * * context: The context pointer passed to DNSServiceEnumerateDomains. - * + * */ -typedef void (*DNSServiceDomainEnumReply) +typedef void (DNSSD_API *DNSServiceDomainEnumReply) ( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, - const char *replyDomain, - void *context + const char *replyDomain, + void *context ); - + + /* DNSServiceEnumerateDomains() Parameters: * * - * sdRef: A pointer to an uninitialized sdRef. May be passed to - * DNSServiceRefDeallocate() to cancel the enumeration. + * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds + * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError, + * and the enumeration operation will run indefinitely until the client + * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate(). * * flags: Possible values are: - * 0 (BrowseDomains) to enumerate domains recommended for browsing. - * 32 (RegistrationDomains) to enumerate domains recommended for registration. + * kDNSServiceFlagsBrowseDomains to enumerate domains recommended for browsing. + * kDNSServiceFlagsRegistrationDomains to enumerate domains recommended + * for registration. * * interfaceIndex: If non-zero, specifies the interface on which to look for domains. * (the index for a given interface is determined via the if_nametoindex() - * family of calls.) Most applications will pass 0 to enumerate domains on - * all interfaces. - * - * callBack: The function to be called when a domain is found or the call asynchronously + * family of calls.) Most applications will pass 0 to enumerate domains on + * all interfaces. See "Constants for specifying an interface index" for more details. + * + * callBack: The function to be called when a domain is found or the call asynchronously * fails. * - * context: An application context pointer which is passed to the callback function + * context: An application context pointer which is passed to the callback function * (may be NULL). * * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating + * errors are delivered to the callback), otherwise returns an error code indicating * the error that occurred (the callback is not invoked and the DNSServiceRef * is not initialized.) */ - -DNSServiceErrorType DNSServiceEnumerateDomains + +DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains ( DNSServiceRef *sdRef, DNSServiceFlags flags, @@ -272,27 +493,28 @@ DNSServiceErrorType DNSServiceEnumerateDomains void *context /* may be NULL */ ); + /********************************************************************************************* * * Service Registration * *********************************************************************************************/ - + /* Register a service that is discovered via Browse() and Resolve() calls. * * * DNSServiceRegisterReply() Callback Parameters: - * + * * sdRef: The DNSServiceRef initialized by DNSServiceRegister(). * * flags: Currently unused, reserved for future use. * - * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will + * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will * indicate the failure that occurred (including name conflicts, if the - * kDNSServiceFlagsNoAutoRenameOnConflict flag was passed to the + * kDNSServiceFlagsNoAutoRename flag was passed to the * callout.) Other parameters are undefined if errorCode is nonzero. * - * name: The service name registered (if the application did not specify a name in + * name: The service name registered (if the application did not specify a name in * DNSServiceRegister(), this indicates what name was automatically chosen). * * regtype: The type of service registered, as it was passed to the callout. @@ -304,87 +526,89 @@ DNSServiceErrorType DNSServiceEnumerateDomains * context: The context pointer that was passed to the callout. * */ - -typedef void (*DNSServiceRegisterReply) + +typedef void (DNSSD_API *DNSServiceRegisterReply) ( DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, - const char *name, - const char *regtype, - const char *domain, - void *context + const char *name, + const char *regtype, + const char *domain, + void *context ); - + + /* DNSServiceRegister() Parameters: * - * sdRef: A pointer to an uninitialized sdRef. If this call succeeds, the reference - * may be passed to - * DNSServiceRefDeallocate() to deregister the service. - * + * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds + * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError, + * and the registration will remain active indefinitely until the client + * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate(). + * * interfaceIndex: If non-zero, specifies the interface on which to register the service * (the index for a given interface is determined via the if_nametoindex() - * family of calls.) Most applications will pass 0 to register on all - * available interfaces. Pass -1 to register a service only on the local - * machine (service will not be visible to remote hosts.) + * family of calls.) Most applications will pass 0 to register on all + * available interfaces. See "Constants for specifying an interface index" for more details. * * flags: Indicates the renaming behavior on name conflict (most applications * will pass 0). See flag definitions above for details. * - * name: If non-NULL, specifies the service name to be registered. - * Most applications will not specify a name, in which case the - * computer name is used (this name is communicated to the client via + * name: If non-NULL, specifies the service name to be registered. + * Most applications will not specify a name, in which case the + * computer name is used (this name is communicated to the client via * the callback). * - * regtype: The service type followed by the protocol, separated by a dot + * regtype: The service type followed by the protocol, separated by a dot * (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". + * New service types should be registered at htp://www.dns-sd.org/ServiceTypes.html. * * domain: If non-NULL, specifies the domain on which to advertise the service. - * Most applications will not specify a domain, instead automatically + * Most applications will not specify a domain, instead automatically * registering in the default domain(s). * * host: If non-NULL, specifies the SRV target host name. Most applications * will not specify a host, instead automatically using the machine's - * default host name(s). Note that specifying a non-NULL host does NOT - * create an address record for that host - the application is responsible + * default host name(s). Note that specifying a non-NULL host does NOT + * create an address record for that host - the application is responsible * for ensuring that the appropriate address record exists, or creating it * via DNSServiceRegisterRecord(). * - * port: The port on which the service accepts connections. Pass 0 for a - * "placeholder" service (i.e. a service that will not be discovered by - * browsing, but will cause a name conflict if another client tries to - * register that same name.) Most clients will not use placeholder services. + * port: The port, in network byte order, on which the service accepts connections. + * Pass 0 for a "placeholder" service (i.e. a service that will not be discovered + * by browsing, but will cause a name conflict if another client tries to + * register that same name). Most clients will not use placeholder services. * * txtLen: The length of the txtRecord, in bytes. Must be zero if the txtRecord is NULL. * - * txtRecord: The txt record rdata. May be NULL. Note that a non-NULL txtRecord - * MUST be a properly formatted DNS TXT record, i.e. + * txtRecord: The txt record rdata. May be NULL. Note that a non-NULL txtRecord + * MUST be a properly formatted DNS TXT record, i.e. * ... * * callBack: The function to be called when the registration completes or asynchronously - * fails. The client MAY pass NULL for the callback - The client will NOT be notified + * fails. The client MAY pass NULL for the callback - The client will NOT be notified * of the default values picked on its behalf, and the client will NOT be notified of any - * asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration + * asynchronous errors (e.g. out of memory errors, etc.) that may prevent the registration * of the service. The client may NOT pass the NoAutoRename flag if the callback is NULL. * The client may still deregister the service at any time via DNSServiceRefDeallocate(). * - * context: An application context pointer which is passed to the callback function + * context: An application context pointer which is passed to the callback function * (may be NULL). * * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating + * errors are delivered to the callback), otherwise returns an error code indicating * the error that occurred (the callback is never invoked and the DNSServiceRef * is not initialized.) * */ -DNSServiceErrorType DNSServiceRegister +DNSServiceErrorType DNSSD_API DNSServiceRegister ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, const char *name, /* may be NULL */ - const char *regtype, + const char *regtype, const char *domain, /* may be NULL */ const char *host, /* may be NULL */ uint16_t port, @@ -393,37 +617,40 @@ DNSServiceErrorType DNSServiceRegister DNSServiceRegisterReply callBack, /* may be NULL */ void *context /* may be NULL */ ); - + + /* DNSServiceAddRecord() * * Add a record to a registered service. The name of the record will be the same as the * registered service's name. - * The record can later be updated or deregistered by passing the RecordRef initialized + * The record can later be updated or deregistered by passing the RecordRef initialized * by this function to DNSServiceUpdateRecord() or DNSServiceRemoveRecord(). * - * + * * Parameters; * * sdRef: A DNSServiceRef initialized by DNSServiceRegister(). - * - * RecordRef: A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this + * + * RecordRef: A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this * call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord(). + * If the above DNSServiceRef is passed to DNSServiceRefDeallocate(), RecordRef is also + * invalidated and may not be used further. * * flags: Currently ignored, reserved for future use. * - * rrtype: The type of the record (e.g. TXT, SRV, etc), as defined in nameser.h. + * rrtype: The type of the record (e.g. kDNSServiceType_TXT, kDNSServiceType_SRV, etc) * * rdlen: The length, in bytes, of the rdata. * * rdata: The raw rdata to be contained in the added resource record. * - * ttl: The time to live of the resource record, in seconds. + * ttl: The time to live of the resource record, in seconds. Pass 0 to use a default value. * * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an * error code indicating the error that occurred (the RecordRef is not initialized). */ -DNSServiceErrorType DNSServiceAddRecord +DNSServiceErrorType DNSSD_API DNSServiceAddRecord ( DNSServiceRef sdRef, DNSRecordRef *RecordRef, @@ -434,6 +661,7 @@ DNSServiceErrorType DNSServiceAddRecord uint32_t ttl ); + /* DNSServiceUpdateRecord * * Update a registered resource record. The record must either be: @@ -462,7 +690,7 @@ DNSServiceErrorType DNSServiceAddRecord * error code indicating the error that occurred. */ -DNSServiceErrorType DNSServiceUpdateRecord +DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord ( DNSServiceRef sdRef, DNSRecordRef RecordRef, /* may be NULL */ @@ -472,9 +700,10 @@ DNSServiceErrorType DNSServiceUpdateRecord uint32_t ttl ); + /* DNSServiceRemoveRecord * - * Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister + * Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister * an record registered individually via DNSServiceRegisterRecord(). * * Parameters: @@ -484,16 +713,16 @@ DNSServiceErrorType DNSServiceUpdateRecord * DNSServiceCreateConnection() (if the record being removed was registered via * DNSServiceRegisterRecord()). * - * recordRef: A DNSRecordRef initialized by a successful call to DNSServiceAddRecord() + * recordRef: A DNSRecordRef initialized by a successful call to DNSServiceAddRecord() * or DNSServiceRegisterRecord(). - * + * * flags: Currently ignored, reserved for future use. * * return value: Returns kDNSServiceErr_NoError on success, otherwise returns an * error code indicating the error that occurred. */ -DNSServiceErrorType DNSServiceRemoveRecord +DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord ( DNSServiceRef sdRef, DNSRecordRef RecordRef, @@ -507,7 +736,6 @@ DNSServiceErrorType DNSServiceRemoveRecord * *********************************************************************************************/ - /* Browse for instances of a service. * * @@ -515,88 +743,102 @@ DNSServiceErrorType DNSServiceRemoveRecord * * sdRef: The DNSServiceRef initialized by DNSServiceBrowse(). * - * flags: Possible values are MoreComing and Add/Remove. See flag definitions - * for details. + * flags: Possible values are kDNSServiceFlagsMoreComing and kDNSServiceFlagsAdd. + * See flag definitions for details. * * interfaceIndex: The interface on which the service is advertised. This index should - * be passed to DNSServiceResolve() when resolving the service. + * be passed to DNSServiceResolve() when resolving the service. * - * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will + * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will * indicate the failure that occurred. Other parameters are undefined if * the errorCode is nonzero. * - * serviceName: The service name discovered. + * serviceName: The discovered service name. This name should be displayed to the user, + * and stored for subsequent use in the DNSServiceResolve() call. * - * regtype: The service type, as passed in to DNSServiceBrowse(). + * regtype: The service type, which is usually (but not always) the same as was passed + * to DNSServiceBrowse(). One case where the discovered service type may + * not be the same as the requested service type is when using subtypes: + * The client may want to browse for only those ftp servers that allow + * anonymous connections. The client will pass the string "_ftp._tcp,_anon" + * to DNSServiceBrowse(), but the type of the service that's discovered + * is simply "_ftp._tcp". The regtype for each discovered service instance + * should be stored along with the name, so that it can be passed to + * DNSServiceResolve() when the service is later resolved. * - * domain: The domain on which the service was discovered (if the application did not - * specify a domain in DNSServicBrowse(), this indicates the domain on which the - * service was discovered.) + * domain: The domain of the discovered service instance. This may or may not be the + * same as the domain that was passed to DNSServiceBrowse(). The domain for each + * discovered service instance should be stored along with the name, so that + * it can be passed to DNSServiceResolve() when the service is later resolved. * * context: The context pointer that was passed to the callout. * */ -typedef void (*DNSServiceBrowseReply) +typedef void (DNSSD_API *DNSServiceBrowseReply) ( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, - const char *serviceName, - const char *regtype, - const char *replyDomain, - void *context + const char *serviceName, + const char *regtype, + const char *replyDomain, + void *context ); - + + /* DNSServiceBrowse() Parameters: * - * sdRef: A pointer to an uninitialized sdRef. May be passed to - * DNSServiceRefDeallocate() to terminate the browse. + * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds + * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError, + * and the browse operation will run indefinitely until the client + * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate(). * * flags: Currently ignored, reserved for future use. * * interfaceIndex: If non-zero, specifies the interface on which to browse for services * (the index for a given interface is determined via the if_nametoindex() * family of calls.) Most applications will pass 0 to browse on all available - * interfaces. Pass -1 to only browse for services provided on the local host. + * interfaces. See "Constants for specifying an interface index" for more details. * - * regtype: The service type being browsed for followed by the protocol, separated by a + * regtype: The service type being browsed for followed by the protocol, separated by a * dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". * * domain: If non-NULL, specifies the domain on which to browse for services. - * Most applications will not specify a domain, instead browsing on the + * Most applications will not specify a domain, instead browsing on the * default domain(s). * - * callBack: The function to be called when an instance of the service being browsed for + * callBack: The function to be called when an instance of the service being browsed for * is found, or if the call asynchronously fails. * - * context: An application context pointer which is passed to the callback function + * context: An application context pointer which is passed to the callback function * (may be NULL). * * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating + * errors are delivered to the callback), otherwise returns an error code indicating * the error that occurred (the callback is not invoked and the DNSServiceRef * is not initialized.) */ -DNSServiceErrorType DNSServiceBrowse +DNSServiceErrorType DNSSD_API DNSServiceBrowse ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, - const char *regtype, + const char *regtype, const char *domain, /* may be NULL */ DNSServiceBrowseReply callBack, void *context /* may be NULL */ ); + /* DNSServiceResolve() * * Resolve a service name discovered via DNSServiceBrowse() to a target host name, port number, and * txt record. * - * Note: Applications should NOT use DNSServiceResolve() solely for txt record monitoring - use + * Note: Applications should NOT use DNSServiceResolve() solely for txt record monitoring - use * DNSServiceQueryRecord() instead, as it is more efficient for this task. * * Note: When the desired results have been returned, the client MUST terminate the resolve by calling @@ -610,92 +852,95 @@ DNSServiceErrorType DNSServiceBrowse * * sdRef: The DNSServiceRef initialized by DNSServiceResolve(). * - * flags: Possible values are MoreComing and Add/Remove. See flag definitions - * for details. + * flags: Currently unused, reserved for future use. * - * interfaceIndex: The interface on which the service was resolved. + * interfaceIndex: The interface on which the service was resolved. * - * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will + * errorCode: Will be kDNSServiceErr_NoError (0) on success, otherwise will * indicate the failure that occurred. Other parameters are undefined if * the errorCode is nonzero. * * fullname: The full service domain name, in the form ... - * (Any literal dots (".") are escaped with a backslash ("\."), and literal - * backslashes are escaped with a second backslash ("\\"), e.g. a web server - * named "Dr. Pepper" would have the fullname "Dr\.\032Pepper._http._tcp.local."). - * This is the appropriate format to pass to standard system DNS APIs such as - * res_query(), or to the special-purpose functions included in this API that - * take fullname parameters. - * - * hosttarget: The target hostname of the machine providing the service. This name can + * (This name is escaped following standard DNS rules, making it suitable for + * passing to standard system DNS APIs such as res_query(), or to the + * special-purpose functions included in this API that take fullname parameters. + * See "Notes on DNS Name Escaping" earlier in this file for more details.) + * + * hosttarget: The target hostname of the machine providing the service. This name can * be passed to functions like gethostbyname() to identify the host's IP address. * - * port: The port number on which connections are accepted for this service. + * port: The port, in network byte order, on which connections are accepted for this service. * * txtLen: The length of the txt record, in bytes. * * txtRecord: The service's primary txt record, in standard txt record format. * - + * context: The context pointer that was passed to the callout. * */ -typedef void (*DNSServiceResolveReply) +typedef void (DNSSD_API *DNSServiceResolveReply) ( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, - const char *fullname, + const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const char *txtRecord, - void *context + void *context ); - + + /* DNSServiceResolve() Parameters * - * sdRef: A pointer to an uninitialized sdRef. May be passed to - * DNSServiceRefDeallocate() to terminate the resolve. + * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds + * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError, + * and the resolve operation will run indefinitely until the client + * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate(). * * flags: Currently ignored, reserved for future use. * - * interfaceIndex: The interface on which to resolve the service. The client should - * pass the interface on which the servicename was discovered, i.e. - * the interfaceIndex passed to the DNSServiceBrowseReply callback, - * or 0 to resolve the named service on all available interfaces. + * interfaceIndex: The interface on which to resolve the service. If this resolve call is + * as a result of a currently active DNSServiceBrowse() operation, then the + * interfaceIndex should be the index reported in the DNSServiceBrowseReply + * callback. If this resolve call is using information previously saved + * (e.g. in a preference file) for later use, then use interfaceIndex 0, because + * the desired service may now be reachable via a different physical interface. + * See "Constants for specifying an interface index" for more details. * - * name: The servicename to be resolved. + * name: The name of the service instance to be resolved, as reported to the + * DNSServiceBrowseReply() callback. * - * regtype: The service type being resolved followed by the protocol, separated by a - * dot (e.g. "_ftp._tcp"). The transport protocol must be "_tcp" or "_udp". + * regtype: The type of the service instance to be resolved, as reported to the + * DNSServiceBrowseReply() callback. * - * domain: The domain on which the service is registered, i.e. the domain passed - * to the DNSServiceBrowseReply callback. + * domain: The domain of the service instance to be resolved, as reported to the + * DNSServiceBrowseReply() callback. * - * callBack: The function to be called when a result is found, or if the call + * callBack: The function to be called when a result is found, or if the call * asynchronously fails. * - * context: An application context pointer which is passed to the callback function + * context: An application context pointer which is passed to the callback function * (may be NULL). * * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating + * errors are delivered to the callback), otherwise returns an error code indicating * the error that occurred (the callback is never invoked and the DNSServiceRef * is not initialized.) */ - -DNSServiceErrorType DNSServiceResolve +DNSServiceErrorType DNSSD_API DNSServiceResolve ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, - const char *name, - const char *regtype, - const char *domain, + const char *name, + const char *regtype, + const char *domain, DNSServiceResolveReply callBack, void *context /* may be NULL */ ); @@ -707,57 +952,6 @@ DNSServiceErrorType DNSServiceResolve * *********************************************************************************************/ -/* DNS Naming Conventions: - * - * The following functions refer to resource records by their full domain name, unlike the above - * functions which divide the name into servicename/regtype/domain fields. In the above functions, - * a dot (".") is considered to be a literal dot in the servicename field (e.g. "Dr. Pepper") and - * a label separator in the regtype ("_ftp._tcp") or domain ("apple.com") fields. Literal dots in - * the domain field would be escaped with a backslash, and literal backslashes would be escaped with - * a second backslash (this is generally not an issue, as domain names on the Internet today almost - * never use characters other than letters, digits, or hyphens, and the dots are label separators.) - * Furthermore, this is transparent to the caller, so long as the fields are passed between functions - * without manipulation. However, the following, special-purpose calls use a single, full domain name. - * As such, all dots are considered to be label separators, unless escaped, and all backslashes are - * considered to be escape characters, unless preceded by a second backslash. For example, the name - * "Dr. Smith \ Dr. Johnson" could be passed literally as a service name parameter in the above calls, - * but in the special purpose call, the dots and backslash would have to be escaped - * (e.g. "Dr\. Smith \\ Dr\. Johnson._ftp._tcp.apple.com" for an ftp service on the apple.com domain.) - */ - -/* DNSServiceConstructFullName() - * - * Concatenate a three-part domain name (as returned by the above callbacks) into a properly-escaped - * full domain name. Note that callbacks in the above functions ALREADY ESCAPE strings where necessary. - * - * Parameters: - * - * fullName: A pointer to a buffer that where the resulting full domain name is to be written. - * The buffer must be kDNSServiceDiscoveryMaxDomainName (1005) bytes in length to - * accommodate the longest legal domain name without buffer overrun. - * - * service: The service name - any dots or slashes must NOT be escaped. - * May be NULL (to construct a PTR record name, e.g. - * "_ftp._tcp.apple.com"). - * - * regtype: The service type followed by the protocol, separated by a dot - * (e.g. "_ftp._tcp"). - * - * domain: The domain name, e.g. "apple.com". Any literal dots or backslashes - * must be escaped. - * - * return value: Returns 0 on success, -1 on error. - * - */ - -int DNSServiceConstructFullName - ( - char *fullName, - const char *service, /* may be NULL */ - const char *regtype, - const char *domain - ); - /* DNSServiceCreateConnection() * * Create a connection to the daemon allowing efficient registration of @@ -775,12 +969,12 @@ int DNSServiceConstructFullName * case the DNSServiceRef is not initialized). */ -DNSServiceErrorType DNSServiceCreateConnection(DNSServiceRef *sdRef); +DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef); /* DNSServiceRegisterRecord * - * Register an individual resource record on a connected DNSServiceRef. + * Register an individual resource record on a connected DNSServiceRef. * * Note that name conflicts occurring for records registered via this call must be handled * by the client in the callback. @@ -790,80 +984,80 @@ DNSServiceErrorType DNSServiceCreateConnection(DNSServiceRef *sdRef); * * sdRef: The connected DNSServiceRef initialized by * DNSServiceDiscoveryConnect(). - * - * RecordRef: The DNSRecordRef initialized by DNSServiceRegisterRecord(). + * + * RecordRef: The DNSRecordRef initialized by DNSServiceRegisterRecord(). If the above + * DNSServiceRef is passed to DNSServiceRefDeallocate(), this DNSRecordRef is + * invalidated, and may not be used further. * * flags: Currently unused, reserved for future use. * - * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will + * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will * indicate the failure that occurred (including name conflicts.) * Other parameters are undefined if errorCode is nonzero. * * context: The context pointer that was passed to the callout. * */ - - typedef void (*DNSServiceRegisterRecordReply) + + typedef void (DNSSD_API *DNSServiceRegisterRecordReply) ( DNSServiceRef sdRef, DNSRecordRef RecordRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, - void *context + void *context ); - -/* DNSServiceRegisterRecord() Parameters: + +/* DNSServiceRegisterRecord() Parameters: * * sdRef: A DNSServiceRef initialized by DNSServiceCreateConnection(). * - * RecordRef: A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this + * RecordRef: A pointer to an uninitialized DNSRecordRef. Upon succesfull completion of this * call, this ref may be passed to DNSServiceUpdateRecord() or DNSServiceRemoveRecord(). - * (To deregister ALL records registered on a single connected DNSServiceRef + * (To deregister ALL records registered on a single connected DNSServiceRef * and deallocate each of their corresponding DNSServiceRecordRefs, call * DNSServiceRefDealloocate()). * - * flags: Possible values are Shared/Unique (see flag type definitions for details). - * + * flags: Possible values are kDNSServiceFlagsShared or kDNSServiceFlagsUnique + * (see flag type definitions for details). + * * interfaceIndex: If non-zero, specifies the interface on which to register the record * (the index for a given interface is determined via the if_nametoindex() * family of calls.) Passing 0 causes the record to be registered on all interfaces. - * Passing -1 causes the record to only be visible on the local host. + * See "Constants for specifying an interface index" for more details. * * fullname: The full domain name of the resource record. * - * rrtype: The numerical type of the resource record (e.g. PTR, SRV, etc), as defined - * in nameser.h. + * rrtype: The numerical type of the resource record (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc) * - * rrclass: The class of the resource record, as defined in nameser.h (usually 1 for the - * Internet class). + * rrclass: The class of the resource record (usually kDNSServiceClass_IN) * * rdlen: Length, in bytes, of the rdata. * * rdata: A pointer to the raw rdata, as it is to appear in the DNS record. * - * ttl: The time to live of the resource record, in seconds. + * ttl: The time to live of the resource record, in seconds. Pass 0 to use a default value. * - * callBack: The function to be called when a result is found, or if the call + * callBack: The function to be called when a result is found, or if the call * asynchronously fails (e.g. because of a name conflict.) * - * context: An application context pointer which is passed to the callback function + * context: An application context pointer which is passed to the callback function * (may be NULL). * * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating + * errors are delivered to the callback), otherwise returns an error code indicating * the error that occurred (the callback is never invoked and the DNSRecordRef is * not initialized.) */ - -DNSServiceErrorType DNSServiceRegisterRecord +DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord ( DNSServiceRef sdRef, DNSRecordRef *RecordRef, DNSServiceFlags flags, uint32_t interfaceIndex, - const char *fullname, + const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, @@ -882,21 +1076,24 @@ DNSServiceErrorType DNSServiceRegisterRecord * DNSServiceQueryRecordReply() Callback Parameters: * * sdRef: The DNSServiceRef initialized by DNSServiceQueryRecord(). - * - * flags: Possible values are Finished/MoreComing. * - * interfaceIndex: The interface on which the query was resolved (the index for a given + * flags: Possible values are kDNSServiceFlagsMoreComing and + * kDNSServiceFlagsAdd. The Add flag is NOT set for PTR records + * with a ttl of 0, i.e. "Remove" events. + * + * interfaceIndex: The interface on which the query was resolved (the index for a given * interface is determined via the if_nametoindex() family of calls). + * See "Constants for specifying an interface index" for more details. * - * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will - * indicate the failure that occurred. Other parameters are undefined if + * errorCode: Will be kDNSServiceErr_NoError on success, otherwise will + * indicate the failure that occurred. Other parameters are undefined if * errorCode is nonzero. * * fullname: The resource record's full domain name. * - * rrtype: The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h. + * rrtype: The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc) * - * rrclass: The class of the resource record, as defined in nameser.h (usually 1). + * rrclass: The class of the resource record (usually kDNSServiceClass_IN). * * rdlen: The length, in bytes, of the resource record rdata. * @@ -908,93 +1105,104 @@ DNSServiceErrorType DNSServiceRegisterRecord * */ -typedef void (*DNSServiceQueryRecordReply) +typedef void (DNSSD_API *DNSServiceQueryRecordReply) ( DNSServiceRef DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, - const char *fullname, + const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, uint32_t ttl, - void *context + void *context ); + /* DNSServiceQueryRecord() Parameters: * - * sdRef: A pointer to an uninitialized DNSServiceRef. + * sdRef: A pointer to an uninitialized DNSServiceRef. If the call succeeds + * then it initializes the DNSServiceRef, returns kDNSServiceErr_NoError, + * and the query operation will run indefinitely until the client + * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate(). + * + * flags: Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast + * query in a non-local domain. Without setting this flag, unicast queries + * will be one-shot - that is, only answers available at the time of the call + * will be returned. By setting this flag, answers (including Add and Remove + * events) that become available after the initial call is made will generate + * callbacks. This flag has no effect on link-local multicast queries. * - * flags: Currently unused, reserved for future use. - * * interfaceIndex: If non-zero, specifies the interface on which to issue the query * (the index for a given interface is determined via the if_nametoindex() - * family of calls.) Passing 0 causes the name to be queried for on all - * interfaces. Passing -1 causes the name to be queried for only on the - * local host. + * family of calls.) Passing 0 causes the name to be queried for on all + * interfaces. See "Constants for specifying an interface index" for more details. * * fullname: The full domain name of the resource record to be queried for. * - * rrtype: The numerical type of the resource record to be queried for (e.g. PTR, SRV, etc) - * as defined in nameser.h. + * rrtype: The numerical type of the resource record to be queried for + * (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc) * - * rrclass: The class of the resource record, as defined in nameser.h - * (usually 1 for the Internet class). + * rrclass: The class of the resource record (usually kDNSServiceClass_IN). * - * callBack: The function to be called when a result is found, or if the call + * callBack: The function to be called when a result is found, or if the call * asynchronously fails. * - * context: An application context pointer which is passed to the callback function + * context: An application context pointer which is passed to the callback function * (may be NULL). * * return value: Returns kDNSServiceErr_NoError on succeses (any subsequent, asynchronous - * errors are delivered to the callback), otherwise returns an error code indicating + * errors are delivered to the callback), otherwise returns an error code indicating * the error that occurred (the callback is never invoked and the DNSServiceRef * is not initialized.) */ - -DNSServiceErrorType DNSServiceQueryRecord + +DNSServiceErrorType DNSSD_API DNSServiceQueryRecord ( DNSServiceRef *sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, - const char *fullname, + const char *fullname, uint16_t rrtype, uint16_t rrclass, DNSServiceQueryRecordReply callBack, void *context /* may be NULL */ ); + /* DNSServiceReconfirmRecord * - * Instruct the daemon to verify the validity of a resource record that appears to - * be out of date (e.g. because tcp connection to a service's target failed.) - * Causes the record to be flushed from the daemon's cache (as well as all other + * Instruct the daemon to verify the validity of a resource record that appears to + * be out of date (e.g. because tcp connection to a service's target failed.) + * Causes the record to be flushed from the daemon's cache (as well as all other * daemons' caches on the network) if the record is determined to be invalid. * * Parameters: * * flags: Currently unused, reserved for future use. * + * interfaceIndex: If non-zero, specifies the interface of the record in question. + * Passing 0 causes all instances of this record to be reconfirmed. + * * fullname: The resource record's full domain name. * - * rrtype: The resource record's type (e.g. PTR, SRV, etc) as defined in nameser.h. + * rrtype: The resource record's type (e.g. kDNSServiceType_PTR, kDNSServiceType_SRV, etc) * - * rrclass: The class of the resource record, as defined in nameser.h (usually 1). + * rrclass: The class of the resource record (usually kDNSServiceClass_IN). * * rdlen: The length, in bytes, of the resource record rdata. * * rdata: The raw rdata of the resource record. * */ - -void DNSServiceReconfirmRecord + +void DNSSD_API DNSServiceReconfirmRecord ( DNSServiceFlags flags, uint32_t interfaceIndex, - const char *fullname, + const char *fullname, uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, @@ -1002,5 +1210,439 @@ void DNSServiceReconfirmRecord ); -#endif // _DNS_SD_H +/********************************************************************************************* + * + * General Utility Functions + * + *********************************************************************************************/ + +/* DNSServiceConstructFullName() + * + * Concatenate a three-part domain name (as returned by the above callbacks) into a + * properly-escaped full domain name. Note that callbacks in the above functions ALREADY ESCAPE + * strings where necessary. + * + * Parameters: + * + * fullName: A pointer to a buffer that where the resulting full domain name is to be written. + * The buffer must be kDNSServiceMaxDomainName (1005) bytes in length to + * accommodate the longest legal domain name without buffer overrun. + * + * service: The service name - any dots or backslashes must NOT be escaped. + * May be NULL (to construct a PTR record name, e.g. + * "_ftp._tcp.apple.com."). + * + * regtype: The service type followed by the protocol, separated by a dot + * (e.g. "_ftp._tcp"). + * + * domain: The domain name, e.g. "apple.com.". Literal dots or backslashes, + * if any, must be escaped, e.g. "1st\. Floor.apple.com." + * + * return value: Returns 0 on success, -1 on error. + * + */ + +int DNSSD_API DNSServiceConstructFullName + ( + char *fullName, + const char *service, /* may be NULL */ + const char *regtype, + const char *domain + ); + + +/********************************************************************************************* + * + * TXT Record Construction Functions + * + *********************************************************************************************/ + +/* + * A typical calling sequence for TXT record construction is something like: + * + * Client allocates storage for TXTRecord data (e.g. declare buffer on the stack) + * TXTRecordCreate(); + * TXTRecordSetValue(); + * TXTRecordSetValue(); + * TXTRecordSetValue(); + * ... + * DNSServiceRegister( ... TXTRecordGetLength(), TXTRecordGetBytesPtr() ... ); + * TXTRecordDeallocate(); + * Explicitly deallocate storage for TXTRecord data (if not allocated on the stack) + */ + + +/* TXTRecordRef + * + * Opaque internal data type. + * Note: Represents a DNS-SD TXT record. + */ + +typedef struct _TXTRecordRef_t { char privatedata[16]; } TXTRecordRef; + + +/* TXTRecordCreate() + * + * Creates a new empty TXTRecordRef referencing the specified storage. + * + * If the buffer parameter is NULL, or the specified storage size is not + * large enough to hold a key subsequently added using TXTRecordSetValue(), + * then additional memory will be added as needed using malloc(). + * + * On some platforms, when memory is low, malloc() may fail. In this + * case, TXTRecordSetValue() will return kDNSServiceErr_NoMemory, and this + * error condition will need to be handled as appropriate by the caller. + * + * You can avoid the need to handle this error condition if you ensure + * that the storage you initially provide is large enough to hold all + * the key/value pairs that are to be added to the record. + * The caller can precompute the exact length required for all of the + * key/value pairs to be added, or simply provide a fixed-sized buffer + * known in advance to be large enough. + * A no-value (key-only) key requires (1 + key length) bytes. + * A key with empty value requires (1 + key length + 1) bytes. + * A key with non-empty value requires (1 + key length + 1 + value length). + * For most applications, DNS-SD TXT records are generally + * less than 100 bytes, so in most cases a simple fixed-sized + * 256-byte buffer will be more than sufficient. + * Recommended size limits for DNS-SD TXT Records are discussed in + * + * + * Note: When passing parameters to and from these TXT record APIs, + * the key name does not include the '=' character. The '=' character + * is the separator between the key and value in the on-the-wire + * packet format; it is not part of either the key or the value. + * + * txtRecord: A pointer to an uninitialized TXTRecordRef. + * + * bufferLen: The size of the storage provided in the "buffer" parameter. + * + * buffer: The storage used to hold the TXTRecord data. + * This storage must remain valid for as long as + * the TXTRecordRef. + */ + +void DNSSD_API TXTRecordCreate + ( + TXTRecordRef *txtRecord, + uint16_t bufferLen, + void *buffer + ); + + +/* TXTRecordDeallocate() + * + * Releases any resources allocated in the course of preparing a TXT Record + * using TXTRecordCreate()/TXTRecordSetValue()/TXTRecordRemoveValue(). + * Ownership of the buffer provided in TXTRecordCreate() returns to the client. + * + * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). + * + */ + +void DNSSD_API TXTRecordDeallocate + ( + TXTRecordRef *txtRecord + ); + + +/* TXTRecordSetValue() + * + * Adds a key (optionally with value) to a TXTRecordRef. If the "key" already + * exists in the TXTRecordRef, then the current value will be replaced with + * the new value. + * Keys may exist in four states with respect to a given TXT record: + * - Absent (key does not appear at all) + * - Present with no value ("key" appears alone) + * - Present with empty value ("key=" appears in TXT record) + * - Present with non-empty value ("key=value" appears in TXT record) + * For more details refer to "Data Syntax for DNS-SD TXT Records" in + * + * + * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). + * + * key: A null-terminated string which only contains printable ASCII + * values (0x20-0x7E), excluding '=' (0x3D). Keys should be + * 8 characters or less (not counting the terminating null). + * + * valueSize: The size of the value. + * + * value: Any binary value. For values that represent + * textual data, UTF-8 is STRONGLY recommended. + * For values that represent textual data, valueSize + * should NOT include the terminating null (if any) + * at the end of the string. + * If NULL, then "key" will be added with no value. + * If non-NULL but valueSize is zero, then "key=" will be + * added with empty value. + * + * return value: Returns kDNSServiceErr_NoError on success. + * Returns kDNSServiceErr_Invalid if the "key" string contains + * illegal characters. + * Returns kDNSServiceErr_NoMemory if adding this key would + * exceed the available storage. + */ + +DNSServiceErrorType DNSSD_API TXTRecordSetValue + ( + TXTRecordRef *txtRecord, + const char *key, + uint8_t valueSize, /* may be zero */ + const void *value /* may be NULL */ + ); + + +/* TXTRecordRemoveValue() + * + * Removes a key from a TXTRecordRef. The "key" must be an + * ASCII string which exists in the TXTRecordRef. + * + * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). + * + * key: A key name which exists in the TXTRecordRef. + * + * return value: Returns kDNSServiceErr_NoError on success. + * Returns kDNSServiceErr_NoSuchKey if the "key" does not + * exist in the TXTRecordRef. + * + */ + +DNSServiceErrorType DNSSD_API TXTRecordRemoveValue + ( + TXTRecordRef *txtRecord, + const char *key + ); + + +/* TXTRecordGetLength() + * + * Allows you to determine the length of the raw bytes within a TXTRecordRef. + * + * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). + * + * return value: Returns the size of the raw bytes inside a TXTRecordRef + * which you can pass directly to DNSServiceRegister() or + * to DNSServiceUpdateRecord(). + * Returns 0 if the TXTRecordRef is empty. + * + */ + +uint16_t DNSSD_API TXTRecordGetLength + ( + const TXTRecordRef *txtRecord + ); + + +/* TXTRecordGetBytesPtr() + * + * Allows you to retrieve a pointer to the raw bytes within a TXTRecordRef. + * + * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). + * + * return value: Returns a pointer to the raw bytes inside the TXTRecordRef + * which you can pass directly to DNSServiceRegister() or + * to DNSServiceUpdateRecord(). + * + */ + +const void * DNSSD_API TXTRecordGetBytesPtr + ( + const TXTRecordRef *txtRecord + ); + + +/********************************************************************************************* + * + * TXT Record Parsing Functions + * + *********************************************************************************************/ + +/* + * A typical calling sequence for TXT record parsing is something like: + * + * Receive TXT record data in DNSServiceResolve() callback + * if (TXTRecordContainsKey(txtLen, txtRecord, "key")) then do something + * val1ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key1", &len1); + * val2ptr = TXTRecordGetValuePtr(txtLen, txtRecord, "key2", &len2); + * ... + * bcopy(val1ptr, myval1, len1); + * bcopy(val2ptr, myval2, len2); + * ... + * return; + * + * If you wish to retain the values after return from the DNSServiceResolve() + * callback, then you need to copy the data to your own storage using bcopy() + * or similar, as shown in the example above. + * + * If for some reason you need to parse a TXT record you built yourself + * using the TXT record construction functions above, then you can do + * that using TXTRecordGetLength and TXTRecordGetBytesPtr calls: + * TXTRecordGetValue(TXTRecordGetLength(x), TXTRecordGetBytesPtr(x), key, &len); + * + * Most applications only fetch keys they know about from a TXT record and + * ignore the rest. + * However, some debugging tools wish to fetch and display all keys. + * To do that, use the TXTRecordGetCount() and TXTRecordGetItemAtIndex() calls. + */ + +/* TXTRecordContainsKey() + * + * Allows you to determine if a given TXT Record contains a specified key. + * + * txtLen: The size of the received TXT Record. + * + * txtRecord: Pointer to the received TXT Record bytes. + * + * key: A null-terminated ASCII string containing the key name. + * + * return value: Returns 1 if the TXT Record contains the specified key. + * Otherwise, it returns 0. + * + */ + +int DNSSD_API TXTRecordContainsKey + ( + uint16_t txtLen, + const void *txtRecord, + const char *key + ); + + +/* TXTRecordGetValuePtr() + * + * Allows you to retrieve the value for a given key from a TXT Record. + * + * txtLen: The size of the received TXT Record + * + * txtRecord: Pointer to the received TXT Record bytes. + * + * key: A null-terminated ASCII string containing the key name. + * + * valueLen: On output, will be set to the size of the "value" data. + * + * return value: Returns NULL if the key does not exist in this TXT record, + * or exists with no value (to differentiate between + * these two cases use TXTRecordContainsKey()). + * Returns pointer to location within TXT Record bytes + * if the key exists with empty or non-empty value. + * For empty value, valueLen will be zero. + * For non-empty value, valueLen will be length of value data. + */ + +const void * DNSSD_API TXTRecordGetValuePtr + ( + uint16_t txtLen, + const void *txtRecord, + const char *key, + uint8_t *valueLen + ); + + +/* TXTRecordGetCount() + * + * Returns the number of keys stored in the TXT Record. The count + * can be used with TXTRecordGetItemAtIndex() to iterate through the keys. + * + * txtLen: The size of the received TXT Record. + * + * txtRecord: Pointer to the received TXT Record bytes. + * + * return value: Returns the total number of keys in the TXT Record. + * + */ + +uint16_t DNSSD_API TXTRecordGetCount + ( + uint16_t txtLen, + const void *txtRecord + ); + + +/* TXTRecordGetItemAtIndex() + * + * Allows you to retrieve a key name and value pointer, given an index into + * a TXT Record. Legal index values range from zero to TXTRecordGetCount()-1. + * It's also possible to iterate through keys in a TXT record by simply + * calling TXTRecordGetItemAtIndex() repeatedly, beginning with index zero + * and increasing until TXTRecordGetItemAtIndex() returns kDNSServiceErr_Invalid. + * + * On return: + * For keys with no value, *value is set to NULL and *valueLen is zero. + * For keys with empty value, *value is non-NULL and *valueLen is zero. + * For keys with non-empty value, *value is non-NULL and *valueLen is non-zero. + * + * txtLen: The size of the received TXT Record. + * + * txtRecord: Pointer to the received TXT Record bytes. + * + * index: An index into the TXT Record. + * + * keyBufLen: The size of the string buffer being supplied. + * + * key: A string buffer used to store the key name. + * On return, the buffer contains a null-terminated C string + * giving the key name. DNS-SD TXT keys are usually + * 8 characters or less. To hold the maximum possible + * key name, the buffer should be 256 bytes long. + * + * valueLen: On output, will be set to the size of the "value" data. + * + * value: On output, *value is set to point to location within TXT + * Record bytes that holds the value data. + * + * return value: Returns kDNSServiceErr_NoError on success. + * Returns kDNSServiceErr_NoMemory if keyBufLen is too short. + * Returns kDNSServiceErr_Invalid if index is greater than + * TXTRecordGetCount()-1. + */ + +DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex + ( + uint16_t txtLen, + const void *txtRecord, + uint16_t index, + uint16_t keyBufLen, + char *key, + uint8_t *valueLen, + const void **value + ); + +#ifdef __APPLE_API_PRIVATE + +/* + * Mac OS X specific functionality + * 3rd party clients of this API should not depend on future support or availability of this routine + */ + +/* DNSServiceSetDefaultDomainForUser() + * + * Set the default domain for the caller's UID. Future browse and registration + * calls by this user that do not specify an explicit domain will browse and + * register in this wide-area domain in addition to .local. In addition, this + * domain will be returned as a Browse domain via domain enumeration calls. + * + * + * Parameters: + * + * flags: Pass kDNSServiceFlagsAdd to add a domain for a user. Call without + * this flag set to clear a previously added domain. + * + * domain: The domain to be used for the caller's UID. + * + * return value: Returns kDNSServiceErr_NoError on succeses, otherwise returns + * an error code indicating the error that occurred + */ + +DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser + ( + DNSServiceFlags flags, + const char *domain + ); + +#endif //__APPLE_API_PRIVATE + +#ifdef __cplusplus + } +#endif +#endif /* _DNS_SD_H */ diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/ApplicationVS2002.sln b/mDNSWindows/Applications/DNSServiceBrowser/Windows/ApplicationVS2002.sln new file mode 100644 index 0000000..fe6ce77 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/ApplicationVS2002.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 7.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Application", "ApplicationVS2002.vcproj", "{EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}" +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = All + ConfigName.1 = Debug + ConfigName.2 = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.All.ActiveCfg = All|Win32 + {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.All.Build.0 = All|Win32 + {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Debug.ActiveCfg = Debug|Win32 + {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Debug.Build.0 = Debug|Win32 + {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Release.ActiveCfg = Release|Win32 + {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/ApplicationVS2002.vcproj b/mDNSWindows/Applications/DNSServiceBrowser/Windows/ApplicationVS2002.vcproj new file mode 100644 index 0000000..89316d2 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/ApplicationVS2002.vcproj @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/ApplicationVS2003.sln b/mDNSWindows/Applications/DNSServiceBrowser/Windows/ApplicationVS2003.sln new file mode 100644 index 0000000..0bdb334 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/ApplicationVS2003.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Application", "ApplicationVS2003.vcproj", "{EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + All = All + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.All.ActiveCfg = All|Win32 + {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.All.Build.0 = All|Win32 + {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Debug.ActiveCfg = Debug|Win32 + {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Debug.Build.0 = Debug|Win32 + {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Release.ActiveCfg = Release|Win32 + {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/ApplicationVS2003.vcproj b/mDNSWindows/Applications/DNSServiceBrowser/Windows/ApplicationVS2003.vcproj new file mode 100644 index 0000000..4f9b2bd --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/ApplicationVS2003.vcproj @@ -0,0 +1,264 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/Resources/Application.ico b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Resources/Application.ico new file mode 100644 index 0000000..a992327 Binary files /dev/null and b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Resources/Application.ico differ diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/Resources/Application.rc b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Resources/Application.rc new file mode 100644 index 0000000..1d9c2eb --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Resources/Application.rc @@ -0,0 +1,281 @@ +// Microsoft Visual C++ generated resource script. +// +#include "Resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "Resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif //_WIN32\r\n" + "#include ""Resources\\Application.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAIN_ICON ICON "Application.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CHOOSER_DIALOG DIALOGEX 0, 0, 332, 252 +STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | + WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +CAPTION "Rendezvous Browser for Windows" +MENU IDR_CHOOSER_DIALOG_MENU +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + CONTROL "",IDC_CHOOSER_LIST,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | + LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,116,8,208,136 + CONTROL "",IDC_SERVICE_LIST,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | + LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,8,8,100,136 + CONTROL "",IDC_DOMAIN_LIST,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | + LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,8,152,100,92 + GROUPBOX "Information",IDC_STATIC,116,148,208,96 + RTEXT "Name:",IDC_STATIC,122,164,38,8 + LTEXT "My Device",IDC_INFO_NAME_TEXT,164,164,152,10,SS_SUNKEN + RTEXT "Text:",IDC_STATIC,122,203,38,8 + LTEXT "Information About My Device",IDC_INFO_TEXT_TEXT,164,203, + 152,34,SS_NOPREFIX | SS_SUNKEN + RTEXT "IP address:",IDC_STATIC,122,177,38,8 + LTEXT "123.124.125.126:1234",IDC_INFO_IP_TEXT,164,177,152,10, + SS_SUNKEN + RTEXT "Interface:",IDC_STATIC,122,190,38,8 + LTEXT "123.124.125.126",IDC_INFO_INTERFACE_TEXT,164,190,152,10, + SS_SUNKEN +END + +IDD_ABOUT_DIALOG DIALOGEX 0, 0, 244, 73 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION +CAPTION "About Rendezvous Browser" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + ICON IDR_MAIN_ICON,IDC_ABOUT_APP_ICON,12,12,20,20 + LTEXT "Rendezvous Browser for Windows",IDC_ABOUT_APP_NAME_TEXT, + 44,11,192,12 + LTEXT "Version 1.0d2",IDC_ABOUT_APP_VERSION_TEXT,44,25,192,8 + LTEXT "Copyright (C) 2002-2003 Apple Computer, Inc.", + IDC_ABOUT_COPYRIGHT_TEXT,4,60,156,8 + DEFPUSHBUTTON "OK",IDOK,192,52,44,14 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "Quick & Dirty 1 day hack by Bob Bradley" + VALUE "CompanyName", "Apple Computer, Inc." + VALUE "FileDescription", "Rendezvous Browser for Windows" + VALUE "FileVersion", "1, 0, 0, 1" + VALUE "InternalName", "Rendezvous Browser for Windows" + VALUE "LegalCopyright", "Copyright (C) Apple Computer, Inc. 2001" + VALUE "OriginalFilename", "RendezvousBrowser.exe" + VALUE "ProductName", "Rendezvous Browser for Windows" + VALUE "ProductVersion", "1, 0, 0, 1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_CHOOSER_DIALOG_MENU MENU +BEGIN + POPUP "File" + BEGIN + MENUITEM "Close &Window\tCtrl+W", ID_FILE_CLOSE + MENUITEM SEPARATOR + MENUITEM "Exit", ID_FILE_EXIT + END + POPUP "Help" + BEGIN + MENUITEM "About Rendezvous Browser...", ID_HELP_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_CHOOSER_DIALOG_MENU_ACCELERATORS ACCELERATORS +BEGIN + "S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT + "W", ID_FILE_CLOSE, VIRTKEY, CONTROL, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// RT_MANIFEST +// + +1 RT_MANIFEST +BEGIN + 0x3f3c, 0x6d78, 0x206c, 0x6576, 0x7372, 0x6f69, 0x3d6e, 0x3122, 0x302e, + 0x2022, 0x6e65, 0x6f63, 0x6964, 0x676e, 0x223d, 0x5455, 0x2d46, 0x2238, + 0x7320, 0x6174, 0x646e, 0x6c61, 0x6e6f, 0x3d65, 0x7922, 0x7365, 0x3f22, + 0x203e, 0x0a0d, 0x613c, 0x7373, 0x6d65, 0x6c62, 0x2079, 0x0a0d, 0x2020, + 0x7820, 0x6c6d, 0x736e, 0x223d, 0x7275, 0x3a6e, 0x6373, 0x6568, 0x616d, + 0x2d73, 0x696d, 0x7263, 0x736f, 0x666f, 0x2d74, 0x6f63, 0x3a6d, 0x7361, + 0x2e6d, 0x3176, 0x2022, 0x0a0d, 0x2020, 0x6d20, 0x6e61, 0x6669, 0x7365, + 0x5674, 0x7265, 0x6973, 0x6e6f, 0x223d, 0x2e31, 0x2230, 0x0d3e, 0x3c0a, + 0x7361, 0x6573, 0x626d, 0x796c, 0x6449, 0x6e65, 0x6974, 0x7974, 0x0d20, + 0x200a, 0x2020, 0x7020, 0x6f72, 0x6563, 0x7373, 0x726f, 0x7241, 0x6863, + 0x7469, 0x6365, 0x7574, 0x6572, 0x223d, 0x3878, 0x2236, 0x0d20, 0x200a, + 0x2020, 0x7620, 0x7265, 0x6973, 0x6e6f, 0x223d, 0x2e35, 0x2e31, 0x2e30, + 0x2230, 0x0a0d, 0x2020, 0x2020, 0x7974, 0x6570, 0x223d, 0x6977, 0x336e, + 0x2232, 0x0a0d, 0x2020, 0x2020, 0x616e, 0x656d, 0x223d, 0x7041, 0x2e70, + 0x7865, 0x2265, 0x3e2f, 0x0a0d, 0x2020, 0x2020, 0x643c, 0x7365, 0x7263, + 0x7069, 0x6974, 0x6e6f, 0x413e, 0x7269, 0x6f50, 0x7472, 0x4120, 0x6d64, + 0x6e69, 0x5520, 0x6974, 0x696c, 0x7974, 0x2f3c, 0x6564, 0x6373, 0x6972, + 0x7470, 0x6f69, 0x3e6e, 0x0a0d, 0x2020, 0x2020, 0x643c, 0x7065, 0x6e65, + 0x6564, 0x636e, 0x3e79, 0x0a0d, 0x2020, 0x2020, 0x643c, 0x7065, 0x6e65, + 0x6564, 0x746e, 0x7341, 0x6573, 0x626d, 0x796c, 0x0d3e, 0x200a, 0x2020, + 0x3c20, 0x7361, 0x6573, 0x626d, 0x796c, 0x6449, 0x6e65, 0x6974, 0x7974, + 0x0a0d, 0x2020, 0x2020, 0x2020, 0x2020, 0x7420, 0x7079, 0x3d65, 0x7722, + 0x6e69, 0x3233, 0x0d22, 0x200a, 0x2020, 0x2020, 0x2020, 0x2020, 0x616e, + 0x656d, 0x223d, 0x694d, 0x7263, 0x736f, 0x666f, 0x2e74, 0x6957, 0x646e, + 0x776f, 0x2e73, 0x6f43, 0x6d6d, 0x6e6f, 0x432d, 0x6e6f, 0x7274, 0x6c6f, + 0x2273, 0x0a0d, 0x2020, 0x2020, 0x2020, 0x2020, 0x7620, 0x7265, 0x6973, + 0x6e6f, 0x223d, 0x2e36, 0x2e30, 0x2e30, 0x2230, 0x0a0d, 0x2020, 0x2020, + 0x2020, 0x2020, 0x7020, 0x6275, 0x696c, 0x4b63, 0x7965, 0x6f54, 0x656b, + 0x3d6e, 0x3622, 0x3935, 0x6235, 0x3436, 0x3431, 0x6334, 0x6663, 0x6431, + 0x2266, 0x0a0d, 0x2020, 0x2020, 0x2020, 0x2020, 0x6c20, 0x6e61, 0x7567, + 0x6761, 0x3d65, 0x2a22, 0x0d22, 0x200a, 0x2020, 0x2020, 0x2020, 0x2020, + 0x7270, 0x636f, 0x7365, 0x6f73, 0x4172, 0x6372, 0x6968, 0x6574, 0x7463, + 0x7275, 0x3d65, 0x7822, 0x3638, 0x2f22, 0x0d3e, 0x200a, 0x2020, 0x3c20, + 0x642f, 0x7065, 0x6e65, 0x6564, 0x746e, 0x7341, 0x6573, 0x626d, 0x796c, + 0x0d3e, 0x200a, 0x2020, 0x3c20, 0x642f, 0x7065, 0x6e65, 0x6564, 0x636e, + 0x3e79, 0x0a0d, 0x2f3c, 0x7361, 0x6573, 0x626d, 0x796c, 0x0d3e, "\012" +END + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_ABOUTBOX "&About Rendezvous Browser" + IDS_CHOOSER_DOMAIN_COLUMN_NAME "Domains" + IDP_SOCKETS_INIT_FAILED "Windows sockets initialization failed." + IDS_CHOOSER_SERVICE_COLUMN_NAME "Services" + IDS_CHOOSER_CHOOSER_NAME_COLUMN_NAME "Name" + IDS_CHOOSER_CHOOSER_IP_COLUMN_NAME "IP Address" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "Resources\Application.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/Resources/Application.rc2 b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Resources/Application.rc2 new file mode 100644 index 0000000..bf1983f --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Resources/Application.rc2 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: Application.rc2,v $ +Revision 1.1 2003/08/21 02:06:46 bradley +Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. + +Revision 1.2 2003/08/20 07:06:34 bradley +Update to APSL 2.0. Updated change history to match other mDNSResponder files. + +Revision 1.1 2002/09/20 06:12:48 bradley +Rendezvous Browser for Windows + +*/ + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/Resources/Resource.h b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Resources/Resource.h new file mode 100644 index 0000000..5329fc1 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Resources/Resource.h @@ -0,0 +1,45 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Application.rc +// +#define IDS_ABOUTBOX 101 +#define IDS_CHOOSER_DOMAIN_COLUMN_NAME 102 +#define IDP_SOCKETS_INIT_FAILED 103 +#define IDS_CHOOSER_SERVICE_COLUMN_NAME 104 +#define IDS_CHOOSER_CHOOSER_NAME_COLUMN_NAME 105 +#define IDS_CHOOSER_CHOOSER_IP_COLUMN_NAME 106 +#define IDC_NAME_TEXT2 124 +#define IDC_INFO_NAME_TEXT 124 +#define IDC_DESCRIPTION_TEXT2 125 +#define IDC_INFO_TEXT_TEXT 125 +#define IDC_IP_TEXT2 126 +#define IDC_INFO_IP_TEXT 126 +#define IDC_IP_TEXT3 127 +#define IDC_INFO_INTERFACE_TEXT 127 +#define IDR_MAIN_ICON 128 +#define IDR_CHOOSER_DIALOG_MENU 136 +#define IDD_CHOOSER_DIALOG 143 +#define IDD_ABOUT_DIALOG 144 +#define IDR_CHOOSER_DIALOG_MENU_ACCELERATORS 146 +#define IDC_CHOOSER_LIST 1000 +#define IDC_SERVICE_LIST2 1001 +#define IDC_SERVICE_LIST 1001 +#define IDC_SERVICE_LIST3 1002 +#define IDC_DOMAIN_LIST 1002 +#define IDC_ABOUT_APP_NAME_TEXT 1105 +#define IDC_ABOUT_APP_VERSION_TEXT 1106 +#define IDC_ABOUT_COPYRIGHT_TEXT 1107 +#define IDC_ABOUT_APP_ICON 1108 +#define ID_FILE_EXIT 32771 +#define ID_HELP_ABOUT 32806 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 164 +#define _APS_NEXT_COMMAND_VALUE 32809 +#define _APS_NEXT_CONTROL_VALUE 1182 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/AboutDialog.cpp b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/AboutDialog.cpp new file mode 100644 index 0000000..cd8cafb --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/AboutDialog.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: AboutDialog.cpp,v $ +Revision 1.1 2003/08/21 02:06:47 bradley +Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. + +Revision 1.4 2003/08/12 19:56:28 cheshire +Update to APSL 2.0 + +Revision 1.3 2003/07/02 21:20:06 cheshire + Update copyright notices, etc., in source code comments + +Revision 1.2 2002/09/21 20:44:55 zarzycki +Added APSL info + +Revision 1.1 2002/09/20 06:12:49 bradley +Rendezvous Browser for Windows + +*/ + +#include + +#include "stdafx.h" + +#include "AboutDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +//=========================================================================================================================== +// Message Map +//=========================================================================================================================== + +BEGIN_MESSAGE_MAP(AboutDialog, CDialog) + //{{AFX_MSG_MAP(AboutDialog) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +//=========================================================================================================================== +// AboutDialog +//=========================================================================================================================== + +AboutDialog::AboutDialog(CWnd* pParent /*=NULL*/) + : CDialog(AboutDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(AboutDialog) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +//=========================================================================================================================== +// OnInitDialog +//=========================================================================================================================== + +BOOL AboutDialog::OnInitDialog() +{ + CDialog::OnInitDialog(); + return( true ); +} + +//=========================================================================================================================== +// DoDataExchange +//=========================================================================================================================== + +void AboutDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(AboutDialog) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/AboutDialog.h b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/AboutDialog.h new file mode 100644 index 0000000..11c9149 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/AboutDialog.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: AboutDialog.h,v $ +Revision 1.1 2003/08/21 02:06:47 bradley +Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. + +Revision 1.4 2003/08/12 19:56:28 cheshire +Update to APSL 2.0 + +Revision 1.3 2003/07/02 21:20:06 cheshire + Update copyright notices, etc., in source code comments + +Revision 1.2 2002/09/21 20:44:55 zarzycki +Added APSL info + +Revision 1.1 2002/09/20 06:12:50 bradley +Rendezvous Browser for Windows + +*/ + +#if !defined(AFX_ABOUTDIALOG_H__4B8A04B2_9735_4F4A_AFCA_15F85FB3D763__INCLUDED_) +#define AFX_ABOUTDIALOG_H__4B8A04B2_9735_4F4A_AFCA_15F85FB3D763__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "Resource.h" + +//=========================================================================================================================== +// AboutDialog +//=========================================================================================================================== + +class AboutDialog : public CDialog +{ + public: + + // Creation/Deletion + + AboutDialog(CWnd* pParent = NULL); // standard constructor + + //{{AFX_DATA(AboutDialog) + enum { IDD = IDD_ABOUT_DIALOG }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(AboutDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + protected: + + // Generated message map functions + //{{AFX_MSG(AboutDialog) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_ABOUTDIALOG_H__4B8A04B2_9735_4F4A_AFCA_15F85FB3D763__INCLUDED_) diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/Application.cpp b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/Application.cpp new file mode 100644 index 0000000..396b7e9 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/Application.cpp @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: Application.cpp,v $ +Revision 1.1 2003/08/21 02:06:47 bradley +Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. + +Revision 1.5 2003/08/12 19:56:28 cheshire +Update to APSL 2.0 + +Revision 1.4 2003/07/02 21:20:06 cheshire + Update copyright notices, etc., in source code comments + +Revision 1.3 2002/09/21 20:44:55 zarzycki +Added APSL info + +Revision 1.2 2002/09/20 08:37:34 bradley +Increased the DNS record cache from the default of 64 to 512 entries for larger networks. + +Revision 1.1 2002/09/20 06:12:51 bradley +Rendezvous Browser for Windows + +*/ + +#include + +#include "DNSServices.h" + +#include "Application.h" + +#include "ChooserDialog.h" + +#include "stdafx.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +//=========================================================================================================================== +// Message Map +//=========================================================================================================================== + +BEGIN_MESSAGE_MAP(Application, CWinApp) + //{{AFX_MSG_MAP(Application) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +//=========================================================================================================================== +// Globals +//=========================================================================================================================== + +Application gApp; + +//=========================================================================================================================== +// Application +//=========================================================================================================================== + +Application::Application( void ) +{ + // +} + +//=========================================================================================================================== +// InitInstance +//=========================================================================================================================== + +BOOL Application::InitInstance() +{ + DNSStatus err; + + // WinSock initialization. + + if( !AfxSocketInit() ) + { + AfxMessageBox( IDP_SOCKETS_INIT_FAILED ); + return( FALSE ); + } + + // Standard MFC initialization. + +#if( !defined( AFX_DEPRECATED ) ) + #ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL + #else + Enable3dControlsStatic(); // Call this when linking to MFC statically + #endif +#endif + + InitCommonControls(); + + // Set up DNS Services. + + err = DNSServicesInitialize( 0, 512 ); + assert( err == kDNSNoErr ); + + // Create the chooser dialog. + + ChooserDialog * dialog; + + m_pMainWnd = NULL; + dialog = new ChooserDialog; + dialog->Create( IDD_CHOOSER_DIALOG ); + m_pMainWnd = dialog; + dialog->ShowWindow( SW_SHOW ); + + return( true ); +} + +//=========================================================================================================================== +// ExitInstance +//=========================================================================================================================== + +int Application::ExitInstance( void ) +{ + // Clean up DNS Services. + + DNSServicesFinalize(); + return( 0 ); +} diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/Application.h b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/Application.h new file mode 100644 index 0000000..e174e4f --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/Application.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: Application.h,v $ +Revision 1.1 2003/08/21 02:06:47 bradley +Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. + +Revision 1.4 2003/08/12 19:56:28 cheshire +Update to APSL 2.0 + +Revision 1.3 2003/07/02 21:20:06 cheshire + Update copyright notices, etc., in source code comments + +Revision 1.2 2002/09/21 20:44:55 zarzycki +Added APSL info + +Revision 1.1 2002/09/20 06:12:51 bradley +Rendezvous Browser for Windows + +*/ + +#if !defined(AFX_ADMIN_H__8663733F_6A15_439F_B568_F5A0125CD572__INCLUDED_) +#define AFX_ADMIN_H__8663733F_6A15_439F_B568_F5A0125CD572__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "stdafx.h" + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "Resource.h" + +//=========================================================================================================================== +// Globals +//=========================================================================================================================== + +extern class Application gApp; + +//=========================================================================================================================== +// Application +//=========================================================================================================================== + +class Application : public CWinApp +{ + public: + + // Creation/Deletion + + Application(); + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(Application) + public: + virtual BOOL InitInstance(); + virtual int ExitInstance( void ); + //}}AFX_VIRTUAL + + //{{AFX_MSG(Application) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_ADMIN_H__8663733F_6A15_439F_B568_F5A0125CD572__INCLUDED_) diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp new file mode 100644 index 0000000..ddd81f9 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/ChooserDialog.cpp @@ -0,0 +1,1171 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ChooserDialog.cpp,v $ +Revision 1.1 2003/08/21 02:06:47 bradley +Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. + +Revision 1.7 2003/08/20 06:45:56 bradley +Updated for IP address changes in DNSServices. Added support for browsing for Xserve RAID. + +Revision 1.6 2003/08/12 19:56:28 cheshire +Update to APSL 2.0 + +Revision 1.5 2003/07/13 01:03:55 cheshire +Diffs provided by Bob Bradley to provide provide proper display of Unicode names + +Revision 1.4 2003/07/02 21:20:06 cheshire + Update copyright notices, etc., in source code comments + +Revision 1.3 2002/09/21 20:44:55 zarzycki +Added APSL info + +Revision 1.2 2002/09/20 08:39:21 bradley +Make sure each resolved item matches the selected service type to handle resolved that may have +been queued up on the Windows Message Loop. Reduce column to fit when scrollbar is present. + +Revision 1.1 2002/09/20 06:12:52 bradley +Rendezvous Browser for Windows + +*/ + +#include +#include +#include +#include +#include + +#include +#include + +#include "stdafx.h" + +#include "DNSServices.h" + +#include "Application.h" +#include "AboutDialog.h" +#include "Resource.h" + +#include "ChooserDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#if 0 +#pragma mark == Constants == +#endif + +//=========================================================================================================================== +// Constants +//=========================================================================================================================== + +// Menus + +enum +{ + kChooserMenuIndexFile = 0, + kChooserMenuIndexHelp = 1 +}; + +// Domain List + +#define kDomainListDefaultDomainColumnIndex 0 +#define kDomainListDefaultDomainColumnWidth 140 + +// Service List + +#define kServiceListDefaultServiceColumnIndex 0 +#define kServiceListDefaultServiceColumnWidth 140 + +// Chooser List + +#define kChooserListDefaultNameColumnIndex 0 +#define kChooserListDefaultNameColumnWidth 162 + +#define kChooserListDefaultIPColumnIndex 1 +#define kChooserListDefaultIPColumnWidth 126 + +// Windows User Messages + +#define WM_USER_DOMAIN_ADD ( WM_USER + 0x100 ) +#define WM_USER_DOMAIN_REMOVE ( WM_USER + 0x101 ) +#define WM_USER_SERVICE_ADD ( WM_USER + 0x102 ) +#define WM_USER_SERVICE_REMOVE ( WM_USER + 0x103 ) +#define WM_USER_RESOLVE ( WM_USER + 0x104 ) + +#if 0 +#pragma mark == Constants - Service Table == +#endif + +//=========================================================================================================================== +// Constants - Service Table +//=========================================================================================================================== + +struct KnownServiceEntry +{ + const char * serviceType; + const char * description; + const char * urlScheme; + bool useText; +}; + +static const KnownServiceEntry kKnownServiceTable[] = +{ + { "_airport._tcp.", "AirPort Base Station", "acp://", false }, + { "_afpovertcp._tcp.", "AppleShare Server", "afp://", false }, + { "_ftp._tcp.", "File Transfer (FTP)", "ftp://", false }, + { "_ichat._tcp.", "iChat", "ichat://", false }, + { "_printer._tcp.", "Printer (LPD)", "ldp://", false }, + { "_eppc._tcp.", "Remote AppleEvents", "eppc://", false }, + { "_ssh._tcp.", "Secure Shell (SSH)", "ssh://", false }, + { "_tftp._tcp.", "Trivial File Transfer (TFTP)", "tftp://", false }, + { "_http._tcp.", "Web Server (HTTP)", "http://", true }, + { "_smb._tcp.", "Windows File Sharing", "smb://", false }, + { "_xserveraid._tcp.", "Xserve RAID", "xsr://", false }, + { NULL, NULL, NULL, false }, +}; + +#if 0 +#pragma mark == Structures == +#endif + +//=========================================================================================================================== +// Structures +//=========================================================================================================================== + +struct DomainEventInfo +{ + DNSBrowserEventType eventType; + CString domain; + DNSNetworkAddress ifIP; +}; + +struct ServiceEventInfo +{ + DNSBrowserEventType eventType; + std::string name; + std::string type; + std::string domain; + DNSNetworkAddress ifIP; +}; + +#if 0 +#pragma mark == Prototypes == +#endif + +//=========================================================================================================================== +// Prototypes +//=========================================================================================================================== + +static void + BrowserCallBack( + void * inContext, + DNSBrowserRef inRef, + DNSStatus inStatusCode, + const DNSBrowserEvent * inEvent ); + +static char * DNSNetworkAddressToString( const DNSNetworkAddress *inAddr, char *outString ); + +static DWORD UTF8StringToStringObject( const char *inUTF8, CString &inObject ); + +#if 0 +#pragma mark == Message Map == +#endif + +//=========================================================================================================================== +// Message Map +//=========================================================================================================================== + +BEGIN_MESSAGE_MAP(ChooserDialog, CDialog) + //{{AFX_MSG_MAP(ChooserDialog) + ON_WM_SYSCOMMAND() + ON_NOTIFY(LVN_ITEMCHANGED, IDC_DOMAIN_LIST, OnDomainListChanged) + ON_NOTIFY(LVN_ITEMCHANGED, IDC_SERVICE_LIST, OnServiceListChanged) + ON_NOTIFY(LVN_ITEMCHANGED, IDC_CHOOSER_LIST, OnChooserListChanged) + ON_NOTIFY(NM_DBLCLK, IDC_CHOOSER_LIST, OnChooserListDoubleClick) + ON_COMMAND(ID_HELP_ABOUT, OnAbout) + ON_WM_INITMENUPOPUP() + ON_WM_ACTIVATE() + ON_COMMAND(ID_FILE_CLOSE, OnFileClose) + ON_COMMAND(ID_FILE_EXIT, OnExit) + ON_WM_CLOSE() + ON_WM_NCDESTROY() + //}}AFX_MSG_MAP + ON_MESSAGE( WM_USER_DOMAIN_ADD, OnDomainAdd ) + ON_MESSAGE( WM_USER_DOMAIN_REMOVE, OnDomainRemove ) + ON_MESSAGE( WM_USER_SERVICE_ADD, OnServiceAdd ) + ON_MESSAGE( WM_USER_SERVICE_REMOVE, OnServiceRemove ) + ON_MESSAGE( WM_USER_RESOLVE, OnResolve ) +END_MESSAGE_MAP() + +#if 0 +#pragma mark == Routines == +#endif + +//=========================================================================================================================== +// ChooserDialog +//=========================================================================================================================== + +ChooserDialog::ChooserDialog( CWnd *inParent ) + : CDialog( ChooserDialog::IDD, inParent) +{ + //{{AFX_DATA_INIT(ChooserDialog) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + // Load menu accelerator table. + + mMenuAcceleratorTable = ::LoadAccelerators( AfxGetInstanceHandle(), MAKEINTRESOURCE( IDR_CHOOSER_DIALOG_MENU_ACCELERATORS ) ); + assert( mMenuAcceleratorTable ); + + mBrowser = NULL; + mIsServiceBrowsing = false; +} + +//=========================================================================================================================== +// ~ChooserDialog +//=========================================================================================================================== + +ChooserDialog::~ChooserDialog( void ) +{ + if( mBrowser ) + { + DNSStatus err; + + err = DNSBrowserRelease( mBrowser, 0 ); + assert( err == kDNSNoErr ); + } +} + +//=========================================================================================================================== +// DoDataExchange +//=========================================================================================================================== + +void ChooserDialog::DoDataExchange( CDataExchange *pDX ) +{ + CDialog::DoDataExchange(pDX); + + //{{AFX_DATA_MAP(ChooserDialog) + DDX_Control(pDX, IDC_SERVICE_LIST, mServiceList); + DDX_Control(pDX, IDC_DOMAIN_LIST, mDomainList); + DDX_Control(pDX, IDC_CHOOSER_LIST, mChooserList); + //}}AFX_DATA_MAP +} + +//=========================================================================================================================== +// OnInitDialog +//=========================================================================================================================== + +BOOL ChooserDialog::OnInitDialog( void ) +{ + BOOL result; + CString tempString; + DNSStatus err; + + // Initialize our parent. + + CDialog::OnInitDialog(); + + // Set up the Domain List. + + result = tempString.LoadString( IDS_CHOOSER_DOMAIN_COLUMN_NAME ); + assert( result ); + mDomainList.InsertColumn( 0, tempString, LVCFMT_LEFT, kDomainListDefaultDomainColumnWidth ); + + // Set up the Service List. + + result = tempString.LoadString( IDS_CHOOSER_SERVICE_COLUMN_NAME ); + assert( result ); + mServiceList.InsertColumn( 0, tempString, LVCFMT_LEFT, kServiceListDefaultServiceColumnWidth ); + + PopulateServicesList(); + + // Set up the Chooser List. + + result = tempString.LoadString( IDS_CHOOSER_CHOOSER_NAME_COLUMN_NAME ); + assert( result ); + mChooserList.InsertColumn( 0, tempString, LVCFMT_LEFT, kChooserListDefaultNameColumnWidth ); + + result = tempString.LoadString( IDS_CHOOSER_CHOOSER_IP_COLUMN_NAME ); + assert( result ); + mChooserList.InsertColumn( 1, tempString, LVCFMT_LEFT, kChooserListDefaultIPColumnWidth ); + + // Set up the other controls. + + UpdateInfoDisplay(); + + // Start browsing for domains. + + err = DNSBrowserCreate( 0, BrowserCallBack, this, &mBrowser ); + assert( err == kDNSNoErr ); + + err = DNSBrowserStartDomainSearch( mBrowser, 0 ); + assert( err == kDNSNoErr ); + + return( true ); +} + +//=========================================================================================================================== +// OnFileClose +//=========================================================================================================================== + +void ChooserDialog::OnFileClose() +{ + OnClose(); +} + +//=========================================================================================================================== +// OnActivate +//=========================================================================================================================== + +void ChooserDialog::OnActivate( UINT nState, CWnd* pWndOther, BOOL bMinimized ) +{ + // Always make the active window the "main" window so modal dialogs work better and the app quits after closing + // the last window. + + gApp.m_pMainWnd = this; + + CDialog::OnActivate(nState, pWndOther, bMinimized); +} + +//=========================================================================================================================== +// PostNcDestroy +//=========================================================================================================================== + +void ChooserDialog::PostNcDestroy() +{ + // Call the base class to do the normal cleanup. + + delete this; +} + +//=========================================================================================================================== +// PreTranslateMessage +//=========================================================================================================================== + +BOOL ChooserDialog::PreTranslateMessage(MSG* pMsg) +{ + BOOL result; + + result = false; + assert( mMenuAcceleratorTable ); + if( mMenuAcceleratorTable ) + { + result = ::TranslateAccelerator( m_hWnd, mMenuAcceleratorTable, pMsg ); + } + if( !result ) + { + result = CDialog::PreTranslateMessage( pMsg ); + } + return( result ); +} + +//=========================================================================================================================== +// OnInitMenuPopup +//=========================================================================================================================== + +void ChooserDialog::OnInitMenuPopup( CMenu *pPopupMenu, UINT nIndex, BOOL bSysMenu ) +{ + CDialog::OnInitMenuPopup( pPopupMenu, nIndex, bSysMenu ); + + switch( nIndex ) + { + case kChooserMenuIndexFile: + break; + + case kChooserMenuIndexHelp: + break; + + default: + break; + } +} + +//=========================================================================================================================== +// OnExit +//=========================================================================================================================== + +void ChooserDialog::OnExit() +{ + AfxPostQuitMessage( 0 ); +} + +//=========================================================================================================================== +// OnAbout +//=========================================================================================================================== + +void ChooserDialog::OnAbout() +{ + AboutDialog dialog; + + dialog.DoModal(); +} + +//=========================================================================================================================== +// OnSysCommand +//=========================================================================================================================== + +void ChooserDialog::OnSysCommand( UINT inID, LPARAM inParam ) +{ + CDialog::OnSysCommand( inID, inParam ); +} + +//=========================================================================================================================== +// OnClose +//=========================================================================================================================== + +void ChooserDialog::OnClose() +{ + StopBrowsing(); + + gApp.m_pMainWnd = this; + DestroyWindow(); +} + +//=========================================================================================================================== +// OnNcDestroy +//=========================================================================================================================== + +void ChooserDialog::OnNcDestroy() +{ + gApp.m_pMainWnd = this; + + CDialog::OnNcDestroy(); +} + +//=========================================================================================================================== +// OnDomainListChanged +//=========================================================================================================================== + +void ChooserDialog::OnDomainListChanged( NMHDR *pNMHDR, LRESULT *pResult ) +{ + UNUSED_ALWAYS( pNMHDR ); + + // Domain list changes have similar effects to service list changes so reuse that code path by calling it here. + + OnServiceListChanged( NULL, NULL ); + + *pResult = 0; +} + +//=========================================================================================================================== +// OnServiceListChanged +//=========================================================================================================================== + +void ChooserDialog::OnServiceListChanged( NMHDR *pNMHDR, LRESULT *pResult ) +{ + int selectedType; + int selectedDomain; + + UNUSED_ALWAYS( pNMHDR ); + + // Stop any existing service search. + + StopBrowsing(); + + // If a domain and service type are selected, start searching for the service type on the domain. + + selectedType = mServiceList.GetNextItem( -1, LVNI_SELECTED ); + selectedDomain = mDomainList.GetNextItem( -1, LVNI_SELECTED ); + + if( ( selectedType >= 0 ) && ( selectedDomain >= 0 ) ) + { + CString type; + CString domain; + + type = mServiceTypes[ selectedType ].serviceType.c_str(); + domain = mDomainList.GetItemText( selectedDomain, 0 ); + + StartBrowsing( type, domain ); + } + + if( pResult ) + { + *pResult = 0; + } +} + +//=========================================================================================================================== +// OnChooserListChanged +//=========================================================================================================================== + +void ChooserDialog::OnChooserListChanged( NMHDR *pNMHDR, LRESULT *pResult ) +{ + UNUSED_ALWAYS( pNMHDR ); + + UpdateInfoDisplay(); + *pResult = 0; +} + +//=========================================================================================================================== +// OnChooserListDoubleClick +//=========================================================================================================================== + +void ChooserDialog::OnChooserListDoubleClick( NMHDR *pNMHDR, LRESULT *pResult ) +{ + int selectedItem; + + UNUSED_ALWAYS( pNMHDR ); + + // Display the service instance if it is selected. Otherwise, clear all the info. + + selectedItem = mChooserList.GetNextItem( -1, LVNI_SELECTED ); + if( selectedItem >= 0 ) + { + ServiceInstanceInfo * p; + CString url; + const KnownServiceEntry * service; + + assert( selectedItem < (int) mServiceInstances.size() ); + p = &mServiceInstances[ selectedItem ]; + + // Search for a known service type entry that matches. + + for( service = kKnownServiceTable; service->serviceType; ++service ) + { + if( p->type == service->serviceType ) + { + break; + } + } + if( service->serviceType ) + { + // Create a URL representing the service instance. Special case for SMB (no port number). + + if( strcmp( service->serviceType, "_smb._tcp" ) == 0 ) + { + url.Format( "%s%s/", service->urlScheme, (const char *) p->ip.c_str() ); + } + else + { + const char * text; + + text = service->useText ? p->text.c_str() : ""; + url.Format( "%s%s/%s", service->urlScheme, (const char *) p->ip.c_str(), text ); + } + + // Let the system open the URL in the correct app. + + ShellExecute( NULL, "open", url, "", "c:\\", SW_SHOWNORMAL ); + } + } + *pResult = 0; +} + +//=========================================================================================================================== +// OnCancel +//=========================================================================================================================== + +void ChooserDialog::OnCancel() +{ + // Do nothing. +} + +//=========================================================================================================================== +// PopulateServicesList +//=========================================================================================================================== + +void ChooserDialog::PopulateServicesList( void ) +{ + ServiceTypeVector::iterator i; + CString name; + + // Add a fixed list of known services. + + if( mServiceTypes.empty() ) + { + const KnownServiceEntry * service; + + for( service = kKnownServiceTable; service->serviceType; ++service ) + { + ServiceTypeInfo info; + + info.serviceType = service->serviceType; + info.description = service->description; + info.urlScheme = service->urlScheme; + mServiceTypes.push_back( info ); + } + } + + // Add each service to the list. + + for( i = mServiceTypes.begin(); i != mServiceTypes.end(); ++i ) + { + UTF8StringToStringObject( ( *i ).description.c_str(), name ); + mServiceList.InsertItem( mServiceList.GetItemCount(), name ); + } + + // Select the first service type by default. + + if( !mServiceTypes.empty() ) + { + mServiceList.SetItemState( 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED ); + } +} + +//=========================================================================================================================== +// UpdateInfoDisplay +//=========================================================================================================================== + +void ChooserDialog::UpdateInfoDisplay( void ) +{ + int selectedItem; + std::string name; + CString s; + std::string ip; + std::string ifIP; + std::string text; + CWnd * item; + + // Display the service instance if it is selected. Otherwise, clear all the info. + + selectedItem = mChooserList.GetNextItem( -1, LVNI_SELECTED ); + if( selectedItem >= 0 ) + { + ServiceInstanceInfo * p; + + assert( selectedItem < (int) mServiceInstances.size() ); + p = &mServiceInstances[ selectedItem ]; + + name = p->name; + ip = p->ip; + ifIP = p->ifIP; + text = p->text; + + // Sync up the list items with the actual data (IP address may change). + + mChooserList.SetItemText( selectedItem, 1, ip.c_str() ); + } + + // Name + + item = (CWnd *) this->GetDlgItem( IDC_INFO_NAME_TEXT ); + assert( item ); + UTF8StringToStringObject( name.c_str(), s ); + item->SetWindowText( s ); + + // IP + + item = (CWnd *) this->GetDlgItem( IDC_INFO_IP_TEXT ); + assert( item ); + item->SetWindowText( ip.c_str() ); + + // Interface + + item = (CWnd *) this->GetDlgItem( IDC_INFO_INTERFACE_TEXT ); + assert( item ); + item->SetWindowText( ifIP.c_str() ); + + // Text + + if( text.size() > 255 ) + { + text.resize( 255 ); + } + item = (CWnd *) this->GetDlgItem( IDC_INFO_TEXT_TEXT ); + assert( item ); + item->SetWindowText( text.c_str() ); +} + +#if 0 +#pragma mark - +#endif + +//=========================================================================================================================== +// OnDomainAdd +//=========================================================================================================================== + +LONG ChooserDialog::OnDomainAdd( WPARAM inWParam, LPARAM inLParam ) +{ + DomainEventInfo * p; + std::auto_ptr < DomainEventInfo > pAutoPtr; + int n; + int i; + CString domain; + CString s; + bool found; + + UNUSED_ALWAYS( inWParam ); + + assert( inLParam ); + p = reinterpret_cast ( inLParam ); + pAutoPtr.reset( p ); + + // Search to see if we already know about this domain. If not, add it to the list. + + found = false; + domain = p->domain; + n = mDomainList.GetItemCount(); + for( i = 0; i < n; ++i ) + { + s = mDomainList.GetItemText( i, 0 ); + if( s == domain ) + { + found = true; + break; + } + } + if( !found ) + { + int selectedItem; + + mDomainList.InsertItem( n, domain ); + + // If no domains are selected and the domain being added is a default domain, select it. + + selectedItem = mDomainList.GetNextItem( -1, LVNI_SELECTED ); + if( ( selectedItem < 0 ) && ( p->eventType == kDNSBrowserEventTypeAddDefaultDomain ) ) + { + mDomainList.SetItemState( n, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED ); + } + } + return( 0 ); +} + +//=========================================================================================================================== +// OnDomainRemove +//=========================================================================================================================== + +LONG ChooserDialog::OnDomainRemove( WPARAM inWParam, LPARAM inLParam ) +{ + DomainEventInfo * p; + std::auto_ptr < DomainEventInfo > pAutoPtr; + int n; + int i; + CString domain; + CString s; + bool found; + + UNUSED_ALWAYS( inWParam ); + + assert( inLParam ); + p = reinterpret_cast ( inLParam ); + pAutoPtr.reset( p ); + + // Search to see if we know about this domain. If so, remove it from the list. + + found = false; + domain = p->domain; + n = mDomainList.GetItemCount(); + for( i = 0; i < n; ++i ) + { + s = mDomainList.GetItemText( i, 0 ); + if( s == domain ) + { + found = true; + break; + } + } + if( found ) + { + mDomainList.DeleteItem( i ); + } + return( 0 ); +} + +//=========================================================================================================================== +// OnServiceAdd +//=========================================================================================================================== + +LONG ChooserDialog::OnServiceAdd( WPARAM inWParam, LPARAM inLParam ) +{ + ServiceEventInfo * p; + std::auto_ptr < ServiceEventInfo > pAutoPtr; + + UNUSED_ALWAYS( inWParam ); + + assert( inLParam ); + p = reinterpret_cast ( inLParam ); + pAutoPtr.reset( p ); + + return( 0 ); +} + +//=========================================================================================================================== +// OnServiceRemove +//=========================================================================================================================== + +LONG ChooserDialog::OnServiceRemove( WPARAM inWParam, LPARAM inLParam ) +{ + ServiceEventInfo * p; + std::auto_ptr < ServiceEventInfo > pAutoPtr; + bool found; + int n; + int i; + + UNUSED_ALWAYS( inWParam ); + + assert( inLParam ); + p = reinterpret_cast ( inLParam ); + pAutoPtr.reset( p ); + + // Search to see if we know about this service instance. If so, remove it from the list. + + found = false; + n = (int) mServiceInstances.size(); + for( i = 0; i < n; ++i ) + { + ServiceInstanceInfo * q; + + // If the name, type, domain, and interface match, treat it as the same service instance. + + q = &mServiceInstances[ i ]; + if( ( p->name == q->name ) && + ( p->type == q->type ) && + ( p->domain == q->domain ) ) + { + found = true; + break; + } + } + if( found ) + { + mChooserList.DeleteItem( i ); + assert( i < (int) mServiceInstances.size() ); + mServiceInstances.erase( mServiceInstances.begin() + i ); + } + return( 0 ); +} + +//=========================================================================================================================== +// OnResolve +//=========================================================================================================================== + +LONG ChooserDialog::OnResolve( WPARAM inWParam, LPARAM inLParam ) +{ + ServiceInstanceInfo * p; + std::auto_ptr < ServiceInstanceInfo > pAutoPtr; + int selectedType; + int n; + int i; + bool found; + + UNUSED_ALWAYS( inWParam ); + + assert( inLParam ); + p = reinterpret_cast ( inLParam ); + pAutoPtr.reset( p ); + + // Make sure it is for an item of the correct type. This handles any resolves that may have been queued up. + + selectedType = mServiceList.GetNextItem( -1, LVNI_SELECTED ); + assert( selectedType >= 0 ); + if( selectedType >= 0 ) + { + assert( selectedType <= (int) mServiceTypes.size() ); + if( p->type != mServiceTypes[ selectedType ].serviceType ) + { + goto exit; + } + } + + // Search to see if we know about this service instance. If so, update its info. Otherwise, add it to the list. + + found = false; + n = (int) mServiceInstances.size(); + for( i = 0; i < n; ++i ) + { + ServiceInstanceInfo * q; + + // If the name, type, domain, and interface matches, treat it as the same service instance. + + q = &mServiceInstances[ i ]; + if( ( p->name == q->name ) && + ( p->type == q->type ) && + ( p->domain == q->domain ) && + ( p->ifIP == q->ifIP ) ) + { + found = true; + break; + } + } + if( found ) + { + mServiceInstances[ i ] = *p; + } + else + { + CString s; + + mServiceInstances.push_back( *p ); + UTF8StringToStringObject( p->name.c_str(), s ); + mChooserList.InsertItem( n, s ); + mChooserList.SetItemText( n, 1, p->ip.c_str() ); + + // If this is the only item, select it. + + if( n == 0 ) + { + mChooserList.SetItemState( n, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED ); + } + } + UpdateInfoDisplay(); + +exit: + return( 0 ); +} + +//=========================================================================================================================== +// StartBrowsing +//=========================================================================================================================== + +void ChooserDialog::StartBrowsing( const char *inType, const char *inDomain ) +{ + DNSStatus err; + + assert( mServiceInstances.empty() ); + assert( mChooserList.GetItemCount() == 0 ); + assert( !mIsServiceBrowsing ); + + mChooserList.DeleteAllItems(); + mServiceInstances.clear(); + + mIsServiceBrowsing = true; + err = DNSBrowserStartServiceSearch( mBrowser, kDNSBrowserFlagAutoResolve, inType, inDomain ); + assert( err == kDNSNoErr ); +} + +//=========================================================================================================================== +// StopBrowsing +//=========================================================================================================================== + +void ChooserDialog::StopBrowsing( void ) +{ + // If searching, stop. + + if( mIsServiceBrowsing ) + { + DNSStatus err; + + mIsServiceBrowsing = false; + err = DNSBrowserStopServiceSearch( mBrowser, 0 ); + assert( err == kDNSNoErr ); + } + + // Remove all service instances. + + mChooserList.DeleteAllItems(); + assert( mChooserList.GetItemCount() == 0 ); + mServiceInstances.clear(); + assert( mServiceInstances.empty() ); + UpdateInfoDisplay(); +} + +#if 0 +#pragma mark - +#endif + +//=========================================================================================================================== +// BrowserCallBack +//=========================================================================================================================== + +static void + BrowserCallBack( + void * inContext, + DNSBrowserRef inRef, + DNSStatus inStatusCode, + const DNSBrowserEvent * inEvent ) +{ + ChooserDialog * dialog; + UINT message; + BOOL posted; + + UNUSED_ALWAYS( inStatusCode ); + UNUSED_ALWAYS( inRef ); + + // Check parameters. + + assert( inContext ); + dialog = reinterpret_cast ( inContext ); + + try + { + switch( inEvent->type ) + { + case kDNSBrowserEventTypeRelease: + break; + + // Domains + + case kDNSBrowserEventTypeAddDomain: + case kDNSBrowserEventTypeAddDefaultDomain: + case kDNSBrowserEventTypeRemoveDomain: + { + DomainEventInfo * domain; + std::auto_ptr < DomainEventInfo > domainAutoPtr; + + domain = new DomainEventInfo; + domainAutoPtr.reset( domain ); + + domain->eventType = inEvent->type; + domain->domain = inEvent->data.addDomain.domain; + domain->ifIP = inEvent->data.addDomain.interfaceIP; + + message = ( inEvent->type == kDNSBrowserEventTypeRemoveDomain ) ? WM_USER_DOMAIN_REMOVE : WM_USER_DOMAIN_ADD; + posted = ::PostMessage( dialog->GetSafeHwnd(), message, 0, (LPARAM) domain ); + assert( posted ); + if( posted ) + { + domainAutoPtr.release(); + } + break; + } + + // Services + + case kDNSBrowserEventTypeAddService: + case kDNSBrowserEventTypeRemoveService: + { + ServiceEventInfo * service; + std::auto_ptr < ServiceEventInfo > serviceAutoPtr; + + service = new ServiceEventInfo; + serviceAutoPtr.reset( service ); + + service->eventType = inEvent->type; + service->name = inEvent->data.addService.name; + service->type = inEvent->data.addService.type; + service->domain = inEvent->data.addService.domain; + service->ifIP = inEvent->data.addService.interfaceIP; + + message = ( inEvent->type == kDNSBrowserEventTypeAddService ) ? WM_USER_SERVICE_ADD : WM_USER_SERVICE_REMOVE; + posted = ::PostMessage( dialog->GetSafeHwnd(), message, 0, (LPARAM) service ); + assert( posted ); + if( posted ) + { + serviceAutoPtr.release(); + } + break; + } + + // Resolves + + case kDNSBrowserEventTypeResolved: + { + ServiceInstanceInfo * serviceInstance; + std::auto_ptr < ServiceInstanceInfo > serviceInstanceAutoPtr; + char s[ 32 ]; + + serviceInstance = new ServiceInstanceInfo; + serviceInstanceAutoPtr.reset( serviceInstance ); + + serviceInstance->name = inEvent->data.resolved->name; + serviceInstance->type = inEvent->data.resolved->type; + serviceInstance->domain = inEvent->data.resolved->domain; + serviceInstance->ip = DNSNetworkAddressToString( &inEvent->data.resolved->address, s ); + serviceInstance->ifIP = DNSNetworkAddressToString( &inEvent->data.resolved->interfaceIP, s ); + serviceInstance->text = inEvent->data.resolved->textRecord; + + posted = ::PostMessage( dialog->GetSafeHwnd(), WM_USER_RESOLVE, 0, (LPARAM) serviceInstance ); + assert( posted ); + if( posted ) + { + serviceInstanceAutoPtr.release(); + } + break; + } + + default: + break; + } + } + catch( ... ) + { + // Don't let exceptions escape. + } +} + +//=========================================================================================================================== +// DNSNetworkAddressToString +// +// Note: Currently only supports IPv4 network addresses. +//=========================================================================================================================== + +static char * DNSNetworkAddressToString( const DNSNetworkAddress *inAddr, char *outString ) +{ + const DNSUInt8 * p; + DNSUInt16 port; + + p = inAddr->u.ipv4.addr.v8; + port = ntohs( inAddr->u.ipv4.port.v16 ); + if( port != kDNSPortInvalid ) + { + sprintf( outString, "%u.%u.%u.%u:%u", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ], port ); + } + else + { + sprintf( outString, "%u.%u.%u.%u", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); + } + return( outString ); +} + +//=========================================================================================================================== +// UTF8StringToStringObject +//=========================================================================================================================== + +static DWORD UTF8StringToStringObject( const char *inUTF8, CString &inObject ) +{ + DWORD err; + int n; + BSTR unicode; + + unicode = NULL; + + n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, NULL, 0 ); + if( n > 0 ) + { + unicode = (BSTR) malloc( (size_t)( n * sizeof( wchar_t ) ) ); + if( !unicode ) + { + err = ERROR_INSUFFICIENT_BUFFER; + goto exit; + } + + n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, unicode, n ); + try + { + inObject = unicode; + } + catch( ... ) + { + err = ERROR_NO_UNICODE_TRANSLATION; + goto exit; + } + } + else + { + inObject = ""; + } + err = 0; + +exit: + if( unicode ) + { + free( unicode ); + } + return( err ); +} diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/ChooserDialog.h b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/ChooserDialog.h new file mode 100644 index 0000000..7acb0b5 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/ChooserDialog.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ChooserDialog.h,v $ +Revision 1.1 2003/08/21 02:06:47 bradley +Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. + +Revision 1.4 2003/08/12 19:56:28 cheshire +Update to APSL 2.0 + +Revision 1.3 2003/07/02 21:20:06 cheshire + Update copyright notices, etc., in source code comments + +Revision 1.2 2002/09/21 20:44:55 zarzycki +Added APSL info + +Revision 1.1 2002/09/20 06:12:52 bradley +Rendezvous Browser for Windows + +*/ + +#if !defined(AFX_CHOOSERDIALOG_H__AC258704_B307_4901_9F98_A0AC022FD8AC__INCLUDED_) +#define AFX_CHOOSERDIALOG_H__AC258704_B307_4901_9F98_A0AC022FD8AC__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include +#include + +#include "afxcmn.h" + +#include "Resource.h" + +#include "DNSServices.h" + +//=========================================================================================================================== +// Structures +//=========================================================================================================================== + +struct ServiceInstanceInfo +{ + std::string name; + std::string type; + std::string domain; + std::string ip; + std::string text; + std::string ifIP; +}; + +struct ServiceTypeInfo +{ + std::string serviceType; + std::string description; + std::string urlScheme; +}; + +//=========================================================================================================================== +// ChooserDialog +//=========================================================================================================================== + +class ChooserDialog : public CDialog +{ + public: + + ChooserDialog(CWnd* pParent = NULL); + virtual ~ChooserDialog( void ); + + //{{AFX_DATA(ChooserDialog) + enum { IDD = IDD_CHOOSER_DIALOG }; + CListCtrl mServiceList; + CListCtrl mDomainList; + CListCtrl mChooserList; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(ChooserDialog) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL + + protected: + + typedef std::vector < ServiceInstanceInfo > ServiceInstanceVector; + typedef std::vector < ServiceTypeInfo > ServiceTypeVector; + + HACCEL mMenuAcceleratorTable; + DNSBrowserRef mBrowser; + BOOL mIsServiceBrowsing; + ServiceInstanceVector mServiceInstances; + ServiceTypeVector mServiceTypes; + + public: + + void PopulateServicesList( void ); + void UpdateInfoDisplay( void ); + + void StartBrowsing( const char *inType, const char *inDomain ); + void StopBrowsing( void ); + + protected: + + //{{AFX_MSG(ChooserDialog) + virtual BOOL OnInitDialog(); + afx_msg void OnSysCommand(UINT nID, LPARAM lParam); + afx_msg void OnDomainListChanged(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnServiceListChanged(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnChooserListChanged(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnChooserListDoubleClick(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnAbout(); + afx_msg void OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu); + afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized); + afx_msg void OnFileClose(); + virtual void OnCancel(); + afx_msg void OnExit(); + afx_msg void OnClose(); + afx_msg void OnNcDestroy(); + //}}AFX_MSG + afx_msg LONG OnDomainAdd( WPARAM inWParam, LPARAM inLParam ); + afx_msg LONG OnDomainRemove( WPARAM inWParam, LPARAM inLParam ); + afx_msg LONG OnServiceAdd( WPARAM inWParam, LPARAM inLParam ); + afx_msg LONG OnServiceRemove( WPARAM inWParam, LPARAM inLParam ); + afx_msg LONG OnResolve( WPARAM inWParam, LPARAM inLParam ); + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CHOOSERDIALOG_H__AC258704_B307_4901_9F98_A0AC022FD8AC__INCLUDED_) diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/StdAfx.cpp b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/StdAfx.cpp new file mode 100644 index 0000000..a26a1e7 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/StdAfx.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: StdAfx.cpp,v $ +Revision 1.1 2003/08/21 02:06:47 bradley +Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. + +Revision 1.4 2003/08/12 19:56:28 cheshire +Update to APSL 2.0 + +Revision 1.3 2003/07/02 21:20:06 cheshire + Update copyright notices, etc., in source code comments + +Revision 1.2 2002/09/21 20:44:55 zarzycki +Added APSL info + +Revision 1.1 2002/09/20 06:12:53 bradley +Rendezvous Browser for Windows + +*/ + +#include "stdafx.h" diff --git a/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/StdAfx.h b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/StdAfx.h new file mode 100644 index 0000000..3c16ff7 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/Windows/Sources/StdAfx.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: StdAfx.h,v $ +Revision 1.1 2003/08/21 02:06:47 bradley +Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. + +Revision 1.4 2003/08/12 19:56:28 cheshire +Update to APSL 2.0 + +Revision 1.3 2003/07/02 21:20:06 cheshire + Update copyright notices, etc., in source code comments + +Revision 1.2 2002/09/21 20:44:56 zarzycki +Added APSL info + +Revision 1.1 2002/09/20 06:12:53 bradley +Rendezvous Browser for Windows + +*/ + +#if !defined(AFX_STDAFX_H__424305D2_0A97_4AA0_B9B1_A7D90D18EBA0__INCLUDED_) +#define AFX_STDAFX_H__424305D2_0A97_4AA0_B9B1_A7D90D18EBA0__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include // MFC socket extensions + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#include + +#include "DNSServices.h" + +#include "Application.h" + +#include "ChooserDialog.h" + +#endif // !defined(AFX_STDAFX_H__424305D2_0A97_4AA0_B9B1_A7D90D18EBA0__INCLUDED_) diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Application.vcc b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Application.vcc new file mode 100644 index 0000000..22f443d --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Application.vcc @@ -0,0 +1,37 @@ +; CLW file contains information for the MFC ClassWizard + +[General Info] +Version=1 +LastClass=BrowserDialog +LastTemplate=CDialog +NewFileInclude1=#include "stdafx.h" +NewFileInclude2=#include "Application.h" + +ClassCount=3 +Class1=Application +Class2=BrowserDialog + +ResourceCount=3 +Resource2=IDR_MAINFRAME +Resource3=IDD_APPLICATION_DIALOG + +[CLS:Application] +Type=0 +HeaderFile=Application.h +ImplementationFile=Application.cpp +Filter=N + +[CLS:BrowserDialog] +Type=0 +HeaderFile=BrowserDialog.h +ImplementationFile=BrowserDialog.cpp +Filter=D + + +[DLG:IDD_APPLICATION_DIALOG] +Type=1 +ControlCount=3 +Control1=IDOK,button,1342242817 +Control2=IDCANCEL,button,1342242816 +Control3=IDC_STATIC,static,1342308352 +Class=BrowserDialog diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Application.vcp b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Application.vcp new file mode 100644 index 0000000..7f62479 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Application.vcp @@ -0,0 +1,499 @@ +# Microsoft eMbedded Visual Tools Project File - Name="Application" - Package Owner=<4> +# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (WCE ARMV4) Application" 0xa301 +# TARGTYPE "Win32 (WCE emulator) Application" 0xa601 + +CFG=Application - Win32 (WCE emulator) Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Application.vcn". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Application.vcn" CFG="Application - Win32 (WCE emulator) Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Application - Win32 (WCE emulator) Release" (based on "Win32 (WCE emulator) Application") +!MESSAGE "Application - Win32 (WCE emulator) Debug" (based on "Win32 (WCE emulator) Application") +!MESSAGE "Application - Win32 (WCE ARMV4) Release" (based on "Win32 (WCE ARMV4) Application") +!MESSAGE "Application - Win32 (WCE ARMV4) Debug" (based on "Win32 (WCE ARMV4) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +# PROP ATL_Project 2 + +!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "emulatorRel" +# PROP BASE Intermediate_Dir "emulatorRel" +# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" +# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" +# PROP BASE Target_Dir "" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "emulatorRel" +# PROP Intermediate_Dir "emulatorRel" +# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" +# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /d "_AFXDLL" /r +# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /d "_AFXDLL" /r +CPP=cl.exe +# ADD BASE CPP /nologo /W3 /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /D "_WIN32_WCE_CEPC" /D "_AFXDLL" /Yu"stdafx.h" /Gs8192 /GF /O2 /c +# ADD CPP /nologo /W3 /I "Resources" /I "Sources" /I "..\..\..\DNSServices" /I "..\..\..\..\mDNSCore" /I "..\..\..\..\mDNSCore\PlatformSupport" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /D "_WIN32_WCE_CEPC" /D "_AFXDLL" /Gs8192 /GF /O2 /c +# SUBTRACT CPP /YX /Yc /Yu +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /subsystem:$(CESubsystem) /MACHINE:IX86 +# ADD LINK32 ws2.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /subsystem:$(CESubsystem) /MACHINE:IX86 + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "emulatorDbg" +# PROP BASE Intermediate_Dir "emulatorDbg" +# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" +# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" +# PROP BASE Target_Dir "" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "emulatorDbg" +# PROP Intermediate_Dir "emulatorDbg" +# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" +# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /d "_AFXDLL" /r +# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /d "_AFXDLL" /r +CPP=cl.exe +# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "_WIN32_WCE_CEPC" /D "_AFXDLL" /Yu"stdafx.h" /Gs8192 /GF /c +# ADD CPP /nologo /W3 /WX /Zi /Od /I "Resources" /I "Sources" /I "..\..\..\DNSServices" /I "..\..\..\..\mDNSCore" /I "..\..\..\..\mDNSCore\PlatformSupport" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "_WIN32_WCE_CEPC" /D "_AFXDLL" /FR /Gs8192 /GF /c +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /debug /subsystem:$(CESubsystem) /MACHINE:IX86 +# ADD LINK32 ws2.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /debug /subsystem:$(CESubsystem) /MACHINE:IX86 + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ARMV4Rel" +# PROP BASE Intermediate_Dir "ARMV4Rel" +# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" +# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" +# PROP BASE Target_Dir "" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "ARMV4Rel" +# PROP Intermediate_Dir "ARMV4Rel" +# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" +# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /d "_AFXDLL" /r +# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /d "_AFXDLL" /r +CPP=clarm.exe +# ADD BASE CPP /nologo /W3 /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /D "_AFXDLL" /Yu"stdafx.h" /O2 /M$(CECrtMT) /c +# ADD CPP /nologo /W3 /I "Resources" /I "Sources" /I "..\..\..\DNSServices" /I "..\..\..\..\mDNSCore" /I "..\..\..\..\mDNSCore\PlatformSupport" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /D "_AFXDLL" /O2 /M$(CECrtMT) /c +# SUBTRACT CPP /YX /Yc /Yu +MTL=midl.exe +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM +# ADD LINK32 ws2.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" + +# PROP BASE Use_MFC 2 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "ARMV4Dbg" +# PROP BASE Intermediate_Dir "ARMV4Dbg" +# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" +# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" +# PROP BASE Target_Dir "" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "ARMV4Dbg" +# PROP Intermediate_Dir "ARMV4Dbg" +# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" +# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +RSC=rc.exe +# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /d "_AFXDLL" /r +# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /d "_AFXDLL" /r +CPP=clarm.exe +# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_AFXDLL" /Yu"stdafx.h" /M$(CECrtMTDebug) /c +# ADD CPP /nologo /W3 /Zi /Od /I "Resources" /I "Sources" /I "..\..\..\DNSServices" /I "..\..\..\..\mDNSCore" /I "..\..\..\..\mDNSCore\PlatformSupport" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_AFXDLL" /M$(CECrtMTDebug) /c +# SUBTRACT CPP /YX /Yc /Yu +MTL=midl.exe +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /debug /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM +# ADD LINK32 ws2.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /debug /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM + +!ENDIF + +# Begin Target + +# Name "Application - Win32 (WCE emulator) Release" +# Name "Application - Win32 (WCE emulator) Debug" +# Name "Application - Win32 (WCE ARMV4) Release" +# Name "Application - Win32 (WCE ARMV4) Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Sources\Application.cpp + +!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" + +DEP_CPP_APPLI=\ + "..\..\..\DNSServices\DNSServices.h"\ + ".\Sources\Application.h"\ + ".\Sources\BrowserDialog.h"\ + ".\Sources\StdAfx.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" + +DEP_CPP_APPLI=\ + "..\..\..\DNSServices\DNSServices.h"\ + ".\Sources\Application.h"\ + ".\Sources\BrowserDialog.h"\ + ".\Sources\StdAfx.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" + +DEP_CPP_APPLI=\ + "..\..\..\DNSServices\DNSServices.h"\ + ".\Sources\Application.h"\ + ".\Sources\BrowserDialog.h"\ + ".\Sources\StdAfx.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" + +DEP_CPP_APPLI=\ + "..\..\..\DNSServices\DNSServices.h"\ + ".\Sources\Application.h"\ + ".\Sources\BrowserDialog.h"\ + ".\Sources\StdAfx.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\Sources\Application.h +# End Source File +# Begin Source File + +SOURCE=.\Sources\BrowserDialog.cpp + +!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" + +DEP_CPP_BROWS=\ + ".\Sources\Application.h"\ + ".\Sources\BrowserDialog.h"\ + ".\Sources\StdAfx.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" + +DEP_CPP_BROWS=\ + "..\..\..\DNSServices\DNSServices.h"\ + ".\Sources\Application.h"\ + ".\Sources\BrowserDialog.h"\ + ".\Sources\StdAfx.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" + +DEP_CPP_BROWS=\ + ".\Sources\Application.h"\ + ".\Sources\BrowserDialog.h"\ + ".\Sources\StdAfx.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" + +DEP_CPP_BROWS=\ + ".\Sources\Application.h"\ + ".\Sources\BrowserDialog.h"\ + ".\Sources\StdAfx.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\Sources\BrowserDialog.h +# End Source File +# Begin Source File + +SOURCE=.\Sources\StdAfx.cpp + +!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" + +DEP_CPP_STDAF=\ + ".\Sources\StdAfx.h"\ + +# ADD CPP /Yc"stdafx.h" + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" + +DEP_CPP_STDAF=\ + ".\Sources\StdAfx.h"\ + +# ADD CPP /Yc"stdafx.h" + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" + +DEP_CPP_STDAF=\ + ".\Sources\StdAfx.h"\ + +# ADD CPP /Yc"stdafx.h" + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" + +DEP_CPP_STDAF=\ + ".\Sources\StdAfx.h"\ + +# ADD CPP /Yc"stdafx.h" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\Sources\StdAfx.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\Resources\Application.ico +# End Source File +# Begin Source File + +SOURCE=.\Resources\Application.rc + +!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\Resources\Application.rc2 +# PROP Exclude_From_Scan -1 +# PROP BASE Exclude_From_Build 1 +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\Resources\newres.h +# End Source File +# Begin Source File + +SOURCE=.\Resources\Resource.h +# End Source File +# End Group +# Begin Group "Rendezvous" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\DNSServices\DNSServices.c + +!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" + +DEP_CPP_DNSSE=\ + "..\..\..\DNSServices\DNSServices.h"\ + "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ + "..\..\..\..\mDNSCore\mDNSDebug.h"\ + "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" + +DEP_CPP_DNSSE=\ + "..\..\..\DNSServices\DNSServices.h"\ + "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ + "..\..\..\..\mDNSCore\mDNSDebug.h"\ + "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" + +DEP_CPP_DNSSE=\ + "..\..\..\DNSServices\DNSServices.h"\ + "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ + "..\..\..\..\mDNSCore\mDNSDebug.h"\ + "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" + +DEP_CPP_DNSSE=\ + "..\..\..\DNSServices\DNSServices.h"\ + "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ + "..\..\..\..\mDNSCore\mDNSDebug.h"\ + "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\DNSServices\DNSServices.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\mDNSCore\mDNS.c + +!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" + +DEP_CPP_MDNS_=\ + "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ + "..\..\..\..\mDNSCore\mDNSDebug.h"\ + "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" + +DEP_CPP_MDNS_=\ + "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ + "..\..\..\..\mDNSCore\mDNSDebug.h"\ + "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" + +DEP_CPP_MDNS_=\ + "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ + "..\..\..\..\mDNSCore\mDNSDebug.h"\ + "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" + +DEP_CPP_MDNS_=\ + "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ + "..\..\..\..\mDNSCore\mDNSDebug.h"\ + "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\mDNSCore\mDNSClientAPI.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\mDNSCore\mDNSDebug.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\..\mDNSCore\mDNSPlatformFunctions.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\mDNSWin32.c + +!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" + +DEP_CPP_MDNSW=\ + "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ + "..\..\..\..\mDNSCore\mDNSDebug.h"\ + "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ + "..\..\..\mDNSWin32.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" + +DEP_CPP_MDNSW=\ + "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ + "..\..\..\..\mDNSCore\mDNSDebug.h"\ + "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ + "..\..\..\mDNSWin32.h"\ + +# ADD CPP /W3 + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" + +DEP_CPP_MDNSW=\ + "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ + "..\..\..\..\mDNSCore\mDNSDebug.h"\ + "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ + "..\..\..\mDNSWin32.h"\ + + +!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" + +DEP_CPP_MDNSW=\ + "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ + "..\..\..\..\mDNSCore\mDNSDebug.h"\ + "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ + "..\..\..\mDNSWin32.h"\ + + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\..\mDNSWin32.h +# End Source File +# End Group +# End Target +# End Project diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Application.vcw b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Application.vcw new file mode 100644 index 0000000..11ef513 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Application.vcw @@ -0,0 +1,29 @@ +Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Application"=.\Application.vcp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/Application.ico b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/Application.ico new file mode 100644 index 0000000..51a182e Binary files /dev/null and b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/Application.ico differ diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/Application.rc b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/Application.rc new file mode 100644 index 0000000..c453f27 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/Application.rc @@ -0,0 +1,194 @@ +//Microsoft eMbedded Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" +#include "newres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "#include ""newres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif //_WIN32\r\n" + "#include ""Resources\\Application.rc2"" // non-Microsoft eMbedded Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#include ""wceres.rc"" // WCE-specific components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON DISCARDABLE "Application.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_APPLICATION_DIALOG DIALOG DISCARDABLE 0, 0, 139, 153 +STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION +EXSTYLE WS_EX_APPWINDOW | 0x80000000L +CAPTION "Rendezvous Browser" +FONT 8, "System" +BEGIN + CONTROL "List1",IDC_BROWSE_LIST,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | + WS_BORDER | WS_TABSTOP,7,7,125,141 +END + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "Apple Computer, Inc.\0" + VALUE "FileDescription", "Rendezvous Browser for Windows CE\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "Application\0" + VALUE "LegalCopyright", "Copyright © 2003 Apple Computer, Inc.\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "Application.exe\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "Rendezvous Browser for Windows CE\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_APPLICATION_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 132 + TOPMARGIN, 7 + BOTTOMMARGIN, 146 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDP_SOCKETS_INIT_FAILED "Windows CE sockets initialization failed." + IDS_BROWSER_LIST_COLUMN_NAME "Name" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "Resources\Application.rc2" // non-Microsoft eMbedded Visual C++ edited resources +#include "afxres.rc" // Standard components +#include "wceres.rc" // WCE-specific components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/Application.rc2 b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/Application.rc2 new file mode 100644 index 0000000..29c9fe7 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/Application.rc2 @@ -0,0 +1,13 @@ +// +// APPLICATION.RC2 - resources Microsoft eMbedded Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft eMbedded Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/newres.h b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/newres.h new file mode 100644 index 0000000..31c3a43 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/newres.h @@ -0,0 +1,28 @@ +#ifndef __NEWRES_H__ +#define __NEWRES_H__ + +#define SHMENUBAR RCDATA +#if !(defined(_WIN32_WCE_PSPC) && (_WIN32_WCE >= 300)) + #undef HDS_HORZ + #undef HDS_BUTTONS + #undef HDS_HIDDEN + + #include + // for MenuBar + #define I_IMAGENONE (-2) + #define NOMENU 0xFFFF + #define IDS_SHNEW 1 + #define IDM_SHAREDNEW 10 + #define IDM_SHAREDNEWDEFAULT 11 + + // for Tab Control + #define TCS_SCROLLOPPOSITE 0x0001 // assumes multiline tab + #define TCS_BOTTOM 0x0002 + #define TCS_RIGHT 0x0002 + #define TCS_VERTICAL 0x0080 + #define TCS_MULTISELECT 0x0004 // allow multi-select in button mode + #define TCS_FLATBUTTONS 0x0008 +#endif //_WIN32_WCE_PSPC + + +#endif //__NEWRES_H__ diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/resource.h b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/resource.h new file mode 100644 index 0000000..0337c56 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Resources/resource.h @@ -0,0 +1,22 @@ +//{{NO_DEPENDENCIES}} +// Microsoft eMbedded Visual C++ generated include file. +// Used by Application.rc +// +#define IDD_APPLICATION_DIALOG 102 +#define IDP_SOCKETS_INIT_FAILED 103 +#define IDS_BROWSER_LIST_COLUMN_NAME 104 +#define IDR_MAINFRAME 128 +#define IDC_BROWSE_LIST 1000 +#define IDC_IP_TEXT 1003 +#define IDC_TXT_TEXT 1004 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1005 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/Application.cpp b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/Application.cpp new file mode 100644 index 0000000..ba28f41 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/Application.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: Application.cpp,v $ +Revision 1.1 2003/08/21 02:16:10 bradley +Rendezvous Browser for HTTP services for Windows CE/PocketPC. + +*/ + +#include "stdafx.h" + +#include "DNSServices.h" + +#include "BrowserDialog.h" + +#include "Application.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +//=========================================================================================================================== +// Message Map +//=========================================================================================================================== + +BEGIN_MESSAGE_MAP(Application, CWinApp) + //{{AFX_MSG_MAP(Application) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +//=========================================================================================================================== +// Globals +//=========================================================================================================================== + +Application gApp; + +//=========================================================================================================================== +// Application +//=========================================================================================================================== + +Application::Application() + : CWinApp() +{ + // +} + +//=========================================================================================================================== +// InitInstance +//=========================================================================================================================== + +BOOL Application::InitInstance() +{ + DNSStatus err; + BrowserDialog dialog; + BOOL dnsInitialized; + + dnsInitialized = FALSE; + + if( !AfxSocketInit() ) + { + AfxMessageBox( IDP_SOCKETS_INIT_FAILED ); + goto exit; + } + + err = DNSServicesInitialize( kDNSFlagAdvertise, 0 ); + if( err ) + { + AfxMessageBox( IDP_SOCKETS_INIT_FAILED ); + goto exit; + } + dnsInitialized = TRUE; + + // Display the main browser dialog. + + m_pMainWnd = &dialog; + dialog.DoModal(); + + // Dialog has been closed. Return false to exit the app and not start the app's message pump. + +exit: + if( dnsInitialized ) + { + DNSServicesFinalize(); + } + return( FALSE ); +} diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/Application.h b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/Application.h new file mode 100644 index 0000000..1f4fe13 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/Application.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: Application.h,v $ +Revision 1.1 2003/08/21 02:16:10 bradley +Rendezvous Browser for HTTP services for Windows CE/PocketPC. + +*/ + +#if !defined(AFX_APPLICATION_H__E2E51302_D643_458E_A7A5_5157233D1E5C__INCLUDED_) +#define AFX_APPLICATION_H__E2E51302_D643_458E_A7A5_5157233D1E5C__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "Resource.h" + +//=========================================================================================================================== +// Application +//=========================================================================================================================== + +class Application : public CWinApp +{ + public: + + Application(); + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(Application) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + + //{{AFX_MSG(Application) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_APPLICATION_H__E2E51302_D643_458E_A7A5_5157233D1E5C__INCLUDED_) diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp new file mode 100644 index 0000000..991fc08 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.cpp @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: BrowserDialog.cpp,v $ +Revision 1.1 2003/08/21 02:16:10 bradley +Rendezvous Browser for HTTP services for Windows CE/PocketPC. + +*/ + +#include "stdafx.h" + +#include "Application.h" + +#include "DNSServices.h" + +#include "BrowserDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +//=========================================================================================================================== +// Message Map +//=========================================================================================================================== + +BEGIN_MESSAGE_MAP(BrowserDialog, CDialog) + //{{AFX_MSG_MAP(BrowserDialog) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +static DWORD UTF8StringToStringObject( const char *inUTF8, CString &inObject ); + +//=========================================================================================================================== +// BrowserDialog +//=========================================================================================================================== + +BrowserDialog::BrowserDialog( CWnd *inParent ) + : CDialog( BrowserDialog::IDD, inParent ) +{ + //{{AFX_DATA_INIT(BrowserDialog) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32. + + mIcon = AfxGetApp()->LoadIcon( IDR_MAINFRAME ); +} + +//=========================================================================================================================== +// DoDataExchange +//=========================================================================================================================== + +void BrowserDialog::DoDataExchange( CDataExchange *pDX ) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(BrowserDialog) + DDX_Control(pDX, IDC_BROWSE_LIST, mBrowserList); + //}}AFX_DATA_MAP +} + +//=========================================================================================================================== +// OnInitDialog +//=========================================================================================================================== + +BOOL BrowserDialog::OnInitDialog() +{ + CString s; + + CDialog::OnInitDialog(); + + // Set the icon for this dialog. The framework does this automatically when the application's main window is not a dialog. + + SetIcon( mIcon, TRUE ); // Set big icon + SetIcon( mIcon, FALSE ); // Set small icon + + CenterWindow( GetDesktopWindow() ); + + // Set up the list. + + CRect rect; + + s.LoadString( IDS_BROWSER_LIST_COLUMN_NAME ); + mBrowserList.GetWindowRect( rect ); + mBrowserList.InsertColumn( 0, s, LVCFMT_LEFT, rect.Width() - 8 ); + + // Start browsing for services. + + DNSStatus err; + + err = DNSBrowserCreate( 0, BrowserCallBack, this, &mBrowser ); + if( err ) + { + AfxMessageBox( IDP_SOCKETS_INIT_FAILED ); + goto exit; + } + + err = DNSBrowserStartServiceSearch( mBrowser, 0, "_http._tcp", NULL ); + if( err ) + { + AfxMessageBox( IDP_SOCKETS_INIT_FAILED ); + goto exit; + } + +exit: + return( TRUE ); +} + +//=========================================================================================================================== +// BrowserCallBack [static] +//=========================================================================================================================== + +void + BrowserDialog::BrowserCallBack( + void * inContext, + DNSBrowserRef inRef, + DNSStatus inStatusCode, + const DNSBrowserEvent * inEvent ) +{ + BrowserDialog * dialog; + + DNS_UNUSED( inStatusCode ); + dialog = reinterpret_cast < BrowserDialog * > ( inContext ); + + switch( inEvent->type ) + { + case kDNSBrowserEventTypeAddService: + dialog->BrowserAddService( inEvent->data.addService.name ); + break; + + case kDNSBrowserEventTypeRemoveService: + dialog->BrowserRemoveService( inEvent->data.removeService.name ); + break; + + default: + break; + } +} + +//=========================================================================================================================== +// BrowserAddService +//=========================================================================================================================== + +void BrowserDialog::BrowserAddService( const char *inName ) +{ + BrowserEntry newEntry; + INT_PTR n; + INT_PTR i; + + UTF8StringToStringObject( inName, newEntry.name ); + + n = mBrowserEntries.GetSize(); + for( i = 0; i < n; ++i ) + { + BrowserEntry & entry = mBrowserEntries.ElementAt( i ); + + if( entry.name.CompareNoCase( newEntry.name ) == 0 ) + { + break; + } + } + if( i >= n ) + { + mBrowserEntries.Add( newEntry ); + mBrowserList.InsertItem( i, newEntry.name ); + } +} + +//=========================================================================================================================== +// BrowserRemoveService +//=========================================================================================================================== + +void BrowserDialog::BrowserRemoveService( const char *inName ) +{ + BrowserEntry newEntry; + INT_PTR n; + INT_PTR i; + + UTF8StringToStringObject( inName, newEntry.name ); + + n = mBrowserEntries.GetSize(); + for( i = 0; i < n; ++i ) + { + BrowserEntry & entry = mBrowserEntries.ElementAt( i ); + + if( entry.name.CompareNoCase( newEntry.name ) == 0 ) + { + break; + } + } + if( i < n ) + { + mBrowserEntries.RemoveAt( i ); + mBrowserList.DeleteItem( i ); + } +} + +#if 0 +#pragma mark - +#endif + +//=========================================================================================================================== +// UTF8StringToStringObject +//=========================================================================================================================== + +static DWORD UTF8StringToStringObject( const char *inUTF8, CString &inObject ) +{ + DWORD err; + int n; + wchar_t * unicode; + + unicode = NULL; + + n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, NULL, 0 ); + if( n > 0 ) + { + unicode = (wchar_t *) malloc( (size_t)( n * sizeof( wchar_t ) ) ); + if( !unicode ) { err = ERROR_INSUFFICIENT_BUFFER; goto exit; }; + + n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, unicode, n ); + inObject = unicode; + } + else + { + inObject = ""; + } + err = 0; + +exit: + if( unicode ) + { + free( unicode ); + } + return( err ); +} diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.h b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.h new file mode 100644 index 0000000..7777510 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/BrowserDialog.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: BrowserDialog.h,v $ +Revision 1.1 2003/08/21 02:16:10 bradley +Rendezvous Browser for HTTP services for Windows CE/PocketPC. + +*/ + +#if !defined(AFX_BROWSERDIALOG_H__DECC5C82_C1C6_4630_B8D5_E1DDE570A061__INCLUDED_) +#define AFX_BROWSERDIALOG_H__DECC5C82_C1C6_4630_B8D5_E1DDE570A061__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +#include "afxtempl.h" +#include "Resource.h" + +#include "DNSServices.h" + +//=========================================================================================================================== +// BrowserDialog +//=========================================================================================================================== + +class BrowserDialog : public CDialog +{ + public: + + BrowserDialog( CWnd *inParent = NULL ); + + //{{AFX_DATA(BrowserDialog) + enum { IDD = IDD_APPLICATION_DIALOG }; + CListCtrl mBrowserList; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(BrowserDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + static void + BrowserCallBack( + void * inContext, + DNSBrowserRef inRef, + DNSStatus inStatusCode, + const DNSBrowserEvent * inEvent ); + + void BrowserAddService( const char *inName ); + void BrowserRemoveService( const char *inName ); + + protected: + + struct BrowserEntry + { + CString name; + }; + + + HICON mIcon; + DNSBrowserRef mBrowser; + CArray < BrowserEntry, BrowserEntry > mBrowserEntries; + + // Generated message map functions + //{{AFX_MSG(BrowserDialog) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_BROWSERDIALOG_H__DECC5C82_C1C6_4630_B8D5_E1DDE570A061__INCLUDED_) diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/StdAfx.cpp b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/StdAfx.cpp new file mode 100644 index 0000000..6622a5d --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/StdAfx.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: StdAfx.cpp,v $ +Revision 1.1 2003/08/21 02:16:10 bradley +Rendezvous Browser for HTTP services for Windows CE/PocketPC. + +*/ + +#include "stdafx.h" diff --git a/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/StdAfx.h b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/StdAfx.h new file mode 100644 index 0000000..3672152 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceBrowser/WindowsCE/Sources/StdAfx.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: StdAfx.h,v $ +Revision 1.1 2003/08/21 02:16:10 bradley +Rendezvous Browser for HTTP services for Windows CE/PocketPC. + +*/ + +#if !defined(AFX_STDAFX_H__7F91E52B_CF39_429D_837D_599CE0B2B3D6__INCLUDED_) +#define AFX_STDAFX_H__7F91E52B_CF39_429D_837D_599CE0B2B3D6__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + + + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions + +#if defined(_AFXDLL) +#include // MFC support for Internet Explorer 4 Common Controls +#endif + +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include // MFC socket extensions + +//{{AFX_INSERT_LOCATION}} +// Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__7F91E52B_CF39_429D_837D_599CE0B2B3D6__INCLUDED_) diff --git a/mDNSWindows/Applications/DNSServiceTest/Tool.c b/mDNSWindows/Applications/DNSServiceTest/Tool.c new file mode 100644 index 0000000..7e49566 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceTest/Tool.c @@ -0,0 +1,1047 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: Tool.c,v $ +Revision 1.7 2003/08/20 07:06:34 bradley +Update to APSL 2.0. Updated change history to match other mDNSResponder files. + +Revision 1.6 2003/08/20 06:50:55 bradley +Updated to latest internal version of the Rendezvous for Windows code: Re-did everything to support +the latest DNSServices APIs (proxies, record updates, etc.); Added support for testing the platform +neutral DNSServices-based emulation layer for the Mac OS X DNSServiceDiscovery API. + +*/ + +#if( defined( _MSC_VER ) ) + #pragma warning( disable:4068 ) // Disable "unknown pragma" warning for "pragma unused". + #pragma warning( disable:4127 ) // Disable "conditional expression is constant" warning for debug macros. + #pragma warning( disable:4311 ) // Disable "type cast : pointer truncation from void *const to int". + + // No stdint.h with Visual C++ so emulate it here. + + typedef signed char int8_t; // C99 stdint.h not supported in VC++/VS.NET yet. + typedef unsigned char uint8_t; // C99 stdint.h not supported in VC++/VS.NET yet. + typedef signed short int16_t; // C99 stdint.h not supported in VC++/VS.NET yet. + typedef unsigned short uint16_t; // C99 stdint.h not supported in VC++/VS.NET yet. + typedef signed long int32_t; // C99 stdint.h not supported in VC++/VS.NET yet. + typedef unsigned long uint32_t; // C99 stdint.h not supported in VC++/VS.NET yet. +#else + #include +#endif + +#include +#include + +#if( __MACH__ ) + #include + #include + #include + + #include + #include + + #include +#else + #define WIN32_LEAN_AND_MEAN + + #include + #include +#endif + +#include "DNSServices.h" +#include "DNSServiceDiscovery.h" + +//=========================================================================================================================== +// Macros +//=========================================================================================================================== + +#if( !TARGET_OS_MAC ) + #define require_action_string( X, LABEL, ACTION, STR ) \ + do \ + { \ + if( !( X ) ) \ + { \ + fprintf( stderr, "%s\n", ( STR ) ); \ + { ACTION; } \ + goto LABEL; \ + } \ + } while( 0 ) + + #define require_string( X, LABEL, STR ) \ + do \ + { \ + if( !( X ) ) \ + { \ + fprintf( stderr, "%s\n", ( STR ) ); \ + goto LABEL; \ + \ + } \ + } while( 0 ) + + #define require_noerr_string( ERR, LABEL, STR ) \ + do \ + { \ + if( ( ERR ) != 0 ) \ + { \ + fprintf( stderr, "%s (%ld)\n", ( STR ), ( ERR ) ); \ + goto LABEL; \ + } \ + } while( 0 ) +#endif + +//=========================================================================================================================== +// Prototypes +//=========================================================================================================================== + +int main( int argc, char* argv[] ); +static void Usage( void ); +static int ProcessArgs( int argc, char* argv[] ); +static DNSStatus ProcessPreset( int inPreset ); + +#if( __MACH__ ) + static void SigIntHandler( int inSignalNumber ); +#endif + +#if( defined( WINVER ) ) + static BOOL WINAPI ConsoleControlHandler( DWORD inControlEvent ); +#endif + +static void BrowserCallBack( void *inContext, DNSBrowserRef inRef, DNSStatus inStatusCode, const DNSBrowserEvent *inEvent ); +static void ResolverCallBack( void *inContext, DNSResolverRef inRef, DNSStatus inStatusCode, const DNSResolverEvent *inEvent ); + +static void + RegistrationCallBack( + void * inContext, + DNSRegistrationRef inRef, + DNSStatus inStatusCode, + const DNSRegistrationEvent * inEvent ); + +static void + HostRegistrationCallBack( + void * inContext, + DNSHostRegistrationRef inRef, + DNSStatus inStatusCode, + void * inData ); + +static void + EmulatedBrowserCallBack( + DNSServiceBrowserReplyResultType inResult, + const char * inName, + const char * inType, + const char * inDomain, + DNSServiceDiscoveryReplyFlags inFlags, + void * inContext ); + +static void + EmulatedDomainEnumerationCallBack( + DNSServiceDomainEnumerationReplyResultType inResult, + const char * inDomain, + DNSServiceDiscoveryReplyFlags inFlags, + void * inContext ); + +static void + EmulatedResolverCallBack( + struct sockaddr * inInterfaceAddr, + struct sockaddr * inAddr, + const char * inTextRecord, + DNSServiceDiscoveryReplyFlags inFlags, + void * inContext ); + +static void EmulatedRegistrationCallBack( DNSServiceRegistrationReplyErrorType inResult, void *inContext ); + +static char * IPv4ToString( DNSOpaque32 inIP, char *outString ); + +//=========================================================================================================================== +// Globals +//=========================================================================================================================== + +#if( defined( WINVER ) ) + static volatile int gQuit = 0; +#endif + +static int gPrintTXTRecords = 1; + +// Presets + +typedef struct PresetData PresetData; +struct PresetData +{ + int argc; + char * argv[ 16 ]; +}; + +#if 0 +#pragma mark == Presets == +#endif + +static const PresetData gPresets[] = +{ + /* 01 */ { 2, { "rendezvous", "-bbd" } }, + /* 02 */ { 4, { "rendezvous", "-bs", "_airport._tcp", "local." } }, + /* 03 */ { 4, { "rendezvous", "-bs", "_xserveraid._tcp", "local." } }, + /* 04 */ { 3, { "rendezvous", "-rdb", "apple.com" } }, + /* 05 */ { 7, { "rendezvous", "-rs", "My Fake AirPort", "_airport._tcp", "local.", "1234", "My Fake Info" } }, + /* 06 */ { 7, { "rendezvous", "-rs", "My Fake Xserve RAID", "_xserveraid._tcp", "local.", "1234", "My Fake Info" } }, + /* 07 */ { 7, { "rendezvous", "-rs", "My Fake Web Server", "_http._tcp", "local.", "8080", "index.html" } }, + /* 08 */ { 9, { "rendezvous", "-rps", "www.apple.com", "17.254.0.91", "Apple Web Server", "_http._tcp", "local.", "80", "index.html" } }, +}; + +const int gPresetsCount = sizeof( gPresets ) / sizeof( gPresets[ 0 ] ); + +#if 0 +#pragma mark - +#endif + +//=========================================================================================================================== +// main +//=========================================================================================================================== + +int main( int argc, char* argv[] ) +{ + DNSStatus err; + + // Set up DNS Services and install a Console Control Handler to handle things like control-c signals. + + err = DNSServicesInitialize( kDNSFlagAdvertise, 0 ); + require_noerr_string( err, exit, "could not initialize Rendezvous" ); + +#if( __MACH__ ) + signal( SIGINT, SigIntHandler ); +#endif + +#if( defined( WINVER ) ) + SetConsoleCtrlHandler( ConsoleControlHandler, TRUE ); +#endif + + ProcessArgs( argc, argv ); + +exit: + DNSServicesFinalize(); + return( err ); +} + +//=========================================================================================================================== +// Usage +//=========================================================================================================================== + +static void Usage( void ) +{ + fprintf( stderr, "\n" ); + fprintf( stderr, "rendezvous - Rendezvous Tool 1.0d1\n" ); + fprintf( stderr, "\n" ); + fprintf( stderr, " -bbd 'b'rowse for 'b'rowsing 'd'omains\n" ); + fprintf( stderr, " -brd 'b'rowse for 'r'egistration 'd'omains\n" ); + fprintf( stderr, " -bs 'b'rowse for 's'ervices\n" ); + fprintf( stderr, " -lsi 'l'ookup 's'ervice 'i'nstance\n" ); + fprintf( stderr, " -rdb[d] 'r'egister 'd'omain for 'b'rowsing ['d'efault]\n" ); + fprintf( stderr, " -rdr[d] 'r'egister 'd'omain for 'r'egistration ['d'efault]\n" ); + fprintf( stderr, " -rs 'r'egister 's'ervice\n" ); + fprintf( stderr, " -rps 'r'egister 'p'roxy 's'ervice\n" ); + fprintf( stderr, " -rnss 'r'egister 'n'o 's'uch 's'ervice\n" ); + + fprintf( stderr, " -ebs 'e'mulated 'b'rowse for 's'ervices\n" ); + fprintf( stderr, " -ebd 'e'mulated 'b'rowse for 'd'omains\n" ); + fprintf( stderr, " -elsi 'e'mulated 'l'ookup 's'ervice 'i'nstance\n" ); + fprintf( stderr, " -ers 'e'mulated 'r'egister 's'ervice\n" ); + + fprintf( stderr, " -h[elp] 'h'elp\n" ); + fprintf( stderr, "\n" ); + + fprintf( stderr, " -1 Preset 1 (browse for browsing domains) rendezvous -bbd\n" ); + fprintf( stderr, " -2 Preset 2 (browse for AirPort) rendezvous -bs \"_airport._tcp\" \"local.\"\n" ); + fprintf( stderr, " -3 Preset 3 (browse for Xserve RAID) rendezvous -bs \"_xserveraid._tcp\" \"local.\"\n" ); + fprintf( stderr, " -4 Preset 4 (register apple.com domain) rendezvous -rdb \"apple.com\"\n" ); + fprintf( stderr, " -5 Preset 5 (register fake AirPort) rendezvous -rs \"My Fake AirPort\" \"_airport._tcp\" \"local.\" 1234 \"My Fake Info\"\n" ); + fprintf( stderr, " -6 Preset 6 (register fake Xserve RAID) rendezvous -rs \"My Fake Xserve RAID\" \"_xserveraid._tcp\" \"local.\" 1234 \"My Fake Info\"\n" ); + fprintf( stderr, " -7 Preset 7 (register fake web server) rendezvous -rs \"My Fake Web Server\" \"_http._tcp\" \"local.\" 8080 \"index.html\"\n" ); + fprintf( stderr, "\n" ); +} + +//=========================================================================================================================== +// ProcessArgs +//=========================================================================================================================== + +static int ProcessArgs( int argc, char* argv[] ) +{ + DNSStatus err; + int i; + const char * name; + const char * type; + const char * domain; + int port; + const char * text; + size_t textSize; + DNSBrowserRef browser; + DNSResolverFlags resolverFlags; + DNSDomainRegistrationType domainType; + const char * label; + const char * host; + const char * ip; + unsigned int b[ 4 ]; + DNSNetworkAddress addr; + dns_service_discovery_ref emulatedRef; + + // Parse the command line arguments (ignore first argument since it's just the program name). + + require_action_string( argc >= 2, exit, err = kDNSBadParamErr, "no arguments specified" ); + + for( i = 1; i < argc; ++i ) + { + if( strcmp( argv[ i ], "-bbd" ) == 0 ) + { + // 'b'rowse for 'b'rowsing 'd'omains + + fprintf( stdout, "browsing for browsing domains\n" ); + + err = DNSBrowserCreate( 0, BrowserCallBack, NULL, &browser ); + require_noerr_string( err, exit, "create browser failed" ); + + err = DNSBrowserStartDomainSearch( browser, 0 ); + require_noerr_string( err, exit, "start domain search failed" ); + } + else if( strcmp( argv[ i ], "-brd" ) == 0 ) + { + // 'b'rowse for 'r'egistration 'd'omains + + fprintf( stdout, "browsing for registration domains\n" ); + + err = DNSBrowserCreate( 0, BrowserCallBack, NULL, &browser ); + require_noerr_string( err, exit, "create browser failed" ); + + err = DNSBrowserStartDomainSearch( browser, kDNSBrowserFlagRegistrationDomainsOnly ); + require_noerr_string( err, exit, "start domain search failed" ); + } + else if( strcmp( argv[ i ], "-bs" ) == 0 ) + { + // 'b'rowse for 's'ervices + + require_action_string( argc > ( i + 2 ), exit, err = kDNSBadParamErr, "missing arguments" ); + ++i; + type = argv[ i++ ]; + domain = argv[ i ]; + if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) + { + domain = "local."; + } + fprintf( stdout, "browsing for \"%s.%s\"\n", type, domain ); + + err = DNSBrowserCreate( 0, BrowserCallBack, NULL, &browser ); + require_noerr_string( err, exit, "create browser failed" ); + + err = DNSBrowserStartServiceSearch( browser, kDNSBrowserFlagAutoResolve, type, domain ); + require_noerr_string( err, exit, "start service search failed" ); + } + else if( strcmp( argv[ i ], "-lsi" ) == 0 ) + { + // 'l'ookup 's'ervice 'i'nstance + + require_action_string( argc > ( i + 3 ), exit, err = kDNSBadParamErr, "missing arguments" ); + ++i; + name = argv[ i++ ]; + type = argv[ i++ ]; + domain = argv[ i ]; + if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) + { + domain = "local."; + } + fprintf( stdout, "resolving \"%s.%s.%s\"\n", name, type, domain ); + + resolverFlags = kDNSResolverFlagOnlyIfUnique | + kDNSResolverFlagAutoReleaseByName; + err = DNSResolverCreate( resolverFlags, name, type, domain, ResolverCallBack, 0, NULL, NULL ); + require_noerr_string( err, exit, "create resolver failed" ); + } + else if( ( strcmp( argv[ i ], "-rdb" ) == 0 ) || ( strcmp( argv[ i ], "-rdbd" ) == 0 ) ) + { + // 'r'egister 'd'omain for 'b'rowsing ['d'efault] + + require_action_string( argc > ( i + 1 ), exit, err = kDNSBadParamErr, "missing arguments" ); + if( strcmp( argv[ i ], "-rdb" ) == 0 ) + { + domainType = kDNSDomainRegistrationTypeBrowse; + label = ""; + } + else + { + domainType = kDNSDomainRegistrationTypeBrowseDefault; + label = "default "; + } + ++i; + domain = argv[ i ]; + if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) + { + domain = "local."; + } + fprintf( stdout, "registering \"%s\" as %sbrowse domain\n", domain, label ); + + err = DNSDomainRegistrationCreate( 0, domain, domainType, NULL ); + require_noerr_string( err, exit, "create domain registration failed" ); + } + else if( ( strcmp( argv[ i ], "-rdr" ) == 0 ) || ( strcmp( argv[ i ], "-rdrd" ) == 0 ) ) + { + // 'r'egister 'd'omain for 'r'egistration ['d'efault] + + require_action_string( argc > ( i + 1 ), exit, err = kDNSBadParamErr, "missing arguments" ); + if( strcmp( argv[ i ], "-rdr" ) == 0 ) + { + domainType = kDNSDomainRegistrationTypeRegistration; + label = ""; + } + else + { + domainType = kDNSDomainRegistrationTypeRegistrationDefault; + label = "default "; + } + ++i; + domain = argv[ i ]; + if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) + { + domain = "local."; + } + fprintf( stdout, "registering \"%s\" as %sregistration domain\n", domain, label ); + + err = DNSDomainRegistrationCreate( 0, domain, domainType, NULL ); + require_noerr_string( err, exit, "create domain registration failed" ); + } + else if( strcmp( argv[ i ], "-rs" ) == 0 ) + { + // 'r'egister 's'ervice + + require_action_string( argc > ( i + 5 ), exit, err = kDNSBadParamErr, "missing arguments" ); + ++i; + name = argv[ i++ ]; + type = argv[ i++ ]; + domain = argv[ i++ ]; + port = atoi( argv[ i++ ] ); + text = argv[ i ]; + textSize = strlen( text ); + if( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) + { + domain = "local."; + } + fprintf( stdout, "registering service \"%s.%s.%s\" port %d text \"%s\"\n", name, type, domain, port, text ); + + err = DNSRegistrationCreate( 0, name, type, domain, (DNSPort) port, text, (DNSCount) textSize, NULL, NULL, + RegistrationCallBack, NULL, NULL ); + require_noerr_string( err, exit, "create registration failed" ); + } + else if( strcmp( argv[ i ], "-rps" ) == 0 ) + { + DNSHostRegistrationFlags hostFlags; + + // 'r'egister 'p'roxy 's'ervice + + require_action_string( argc > ( i + 7 ), exit, err = kDNSBadParamErr, "missing arguments" ); + ++i; + host = argv[ i++ ]; + ip = argv[ i++ ]; + name = argv[ i++ ]; + type = argv[ i++ ]; + domain = argv[ i++ ]; + port = atoi( argv[ i++ ] ); + text = argv[ i ]; + textSize = strlen( text ); + if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) + { + domain = "local."; + } + + sscanf( ip, "%u.%u.%u.%u", &b[ 0 ], &b[ 1 ], &b[ 2 ], &b[ 3 ] ); + addr.addressType = kDNSNetworkAddressTypeIPv4; + addr.u.ipv4.addr.v32 = (DNSUInt32)( ( b[ 0 ] << 24 ) | ( b[ 1 ] << 16 ) | ( b[ 2 ] << 8 ) | ( b[ 3 ] << 0 ) ); + + fprintf( stdout, "registering proxy service \"%s.%s.%s\" port %d text \"%s\"\n", name, type, domain, port, text ); + + hostFlags = kDNSHostRegistrationFlagOnlyIfNotFound | kDNSHostRegistrationFlagAutoRenameOnConflict; + err = DNSHostRegistrationCreate( hostFlags, host, domain, &addr, NULL, + HostRegistrationCallBack, NULL, NULL ); + require_noerr_string( err, exit, "create host registration failed" ); + + err = DNSRegistrationCreate( 0, name, type, domain, (DNSPort) port, text, (DNSCount) textSize, host, NULL, + RegistrationCallBack, NULL, NULL ); + require_noerr_string( err, exit, "create registration failed" ); + } + else if( strcmp( argv[ i ], "-rnss" ) == 0 ) + { + // 'r'egister 'n'o 's'uch 's'ervice + + require_action_string( argc > ( i + 3 ), exit, err = kDNSBadParamErr, "missing arguments" ); + ++i; + name = argv[ i++ ]; + type = argv[ i++ ]; + domain = argv[ i++ ]; + if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) + { + domain = "local."; + } + fprintf( stdout, "registering no-such-service \"%s.%s.%s\"\n", name, type, domain ); + + err = DNSNoSuchServiceRegistrationCreate( 0, name, type, domain, NULL, RegistrationCallBack, NULL, NULL ); + require_noerr_string( err, exit, "create no-such-service registration failed" ); + } + else if( strcmp( argv[ i ], "-ebs" ) == 0 ) + { + // 'e'mulated 'b'rowse for 's'ervices + + require_action_string( argc > ( i + 2 ), exit, err = kDNSBadParamErr, "missing arguments" ); + ++i; + type = argv[ i++ ]; + domain = argv[ i ]; + if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) + { + domain = "local."; + } + fprintf( stdout, "emulated browsing for \"%s.%s\"\n", type, domain ); + + emulatedRef = DNSServiceBrowserCreate( type, domain, EmulatedBrowserCallBack, NULL ); + require_action_string( emulatedRef, exit, err = kDNSUnknownErr, "create emulated browser failed" ); + } + else if( strcmp( argv[ i ], "-ebd" ) == 0 ) + { + int registrationOnly; + + // 'e'mulated 'b'rowse for 'd'omains + + require_action_string( argc > ( i + 1 ), exit, err = kDNSBadParamErr, "missing arguments" ); + ++i; + type = argv[ i++ ]; + if( strcmp( type, "registration" ) == 0 ) + { + registrationOnly = 1; + } + else if( strcmp( type, "browse" ) == 0 ) + { + registrationOnly = 0; + } + else + { + require_action_string( 0, exit, err = kDNSBadParamErr, "invalid browse type" ); + } + fprintf( stdout, "emulated browsing for %s domains\n", type ); + + emulatedRef = DNSServiceDomainEnumerationCreate( registrationOnly, EmulatedDomainEnumerationCallBack, NULL ); + require_action_string( emulatedRef, exit, err = kDNSUnknownErr, "create emulated domain browser failed" ); + } + else if( strcmp( argv[ i ], "-elsi" ) == 0 ) + { + // 'e'mulated 'l'ookup 's'ervice 'i'nstance + + require_action_string( argc > ( i + 3 ), exit, err = kDNSBadParamErr, "missing arguments" ); + ++i; + name = argv[ i++ ]; + type = argv[ i++ ]; + domain = argv[ i ]; + if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) + { + domain = "local."; + } + fprintf( stdout, "emulated resolving \"%s.%s.%s\"\n", name, type, domain ); + + emulatedRef = DNSServiceResolverResolve( name, type, domain, EmulatedResolverCallBack, NULL ); + require_action_string( emulatedRef, exit, err = kDNSUnknownErr, "create emulated resolver failed" ); + } + else if( strcmp( argv[ i ], "-ers" ) == 0 ) + { + // 'e'mulated 'r'egister 's'ervice + + require_action_string( argc > ( i + 5 ), exit, err = kDNSBadParamErr, "missing arguments" ); + ++i; + name = argv[ i++ ]; + type = argv[ i++ ]; + domain = argv[ i++ ]; + port = atoi( argv[ i++ ] ); + text = argv[ i ]; + textSize = strlen( text ); + if( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) + { + domain = "local."; + } + fprintf( stdout, "registering service \"%s.%s.%s\" port %d text \"%s\"\n", name, type, domain, port, text ); + + emulatedRef = DNSServiceRegistrationCreate( name, type, domain, (uint16_t) port, text, + EmulatedRegistrationCallBack, NULL ); + require_action_string( emulatedRef, exit, err = kDNSUnknownErr, "create emulated registration failed" ); + } + else if( ( argv[ i ][ 0 ] == '-' ) && isdigit( argv[ i ][ 1 ] ) ) + { + // Preset + + ProcessPreset( atoi( &argv[ i ][ 1 ] ) ); + err = 0; + goto exit; + } + else if( strcmp( argv[ i ], "-q" ) == 0 ) + { + // Quiet (no text records) + + gPrintTXTRecords = 0; + } + else if( ( strcmp( argv[ i ], "-help" ) == 0 ) || ( strcmp( argv[ i ], "-h" ) == 0 ) ) + { + // Help + + Usage(); + err = 0; + goto exit; + } + else + { + // Unknown parameter. + + require_action_string( 0, exit, err = kDNSBadParamErr, "unknown parameter" ); + goto exit; + } + } + + // Run until control-C'd. + + #if( __MACH__ ) + CFRunLoopRun(); + #endif + + #if( defined( WINVER ) ) + while( !gQuit ) + { + Sleep( 200 ); + } + #endif + + err = kDNSNoErr; + +exit: + if( err ) + { + Usage(); + } + return( err ); +} + +//=========================================================================================================================== +// ProcessPreset +//=========================================================================================================================== + +static DNSStatus ProcessPreset( int inPreset ) +{ + DNSStatus err; + + require_action_string( ( inPreset > 0 ) && ( inPreset <= gPresetsCount ), exit, err = kDNSBadParamErr, "invalid preset" ); + + err = ProcessArgs( gPresets[ inPreset - 1 ].argc, (char **) gPresets[ inPreset - 1 ].argv ); + +exit: + return( err ); +} + +#if( __MACH__ ) +//=========================================================================================================================== +// SigIntHandler +//=========================================================================================================================== + +static void SigIntHandler( int inSignalNumber ) +{ + DNS_UNUSED( inSignalNumber ); + + signal( SIGINT, SIG_DFL ); + CFRunLoopStop( CFRunLoopGetCurrent() ); +} +#endif + +#if( defined( WINVER ) ) +//=========================================================================================================================== +// ConsoleControlHandler +//=========================================================================================================================== + +static BOOL WINAPI ConsoleControlHandler( DWORD inControlEvent ) +{ + BOOL handled; + + handled = 0; + switch( inControlEvent ) + { + case CTRL_C_EVENT: + case CTRL_BREAK_EVENT: + case CTRL_CLOSE_EVENT: + case CTRL_LOGOFF_EVENT: + case CTRL_SHUTDOWN_EVENT: + gQuit = 1; + handled = 1; + break; + + default: + break; + } + return( handled ); +} +#endif + +//=========================================================================================================================== +// BrowserCallBack +//=========================================================================================================================== + +static void BrowserCallBack( void *inContext, DNSBrowserRef inRef, DNSStatus inStatusCode, const DNSBrowserEvent *inEvent ) +{ + char ifIP[ 32 ]; + char ip[ 32 ]; + + DNS_UNUSED( inContext ); + DNS_UNUSED( inRef ); + DNS_UNUSED( inStatusCode ); + + switch( inEvent->type ) + { + case kDNSBrowserEventTypeRelease: + break; + + case kDNSBrowserEventTypeAddDomain: + fprintf( stdout, "domain \"%s\" added on interface 0x%08X (%s)\n", + inEvent->data.addDomain.domain, + (int) inEvent->data.addDomain.interfaceID, + IPv4ToString( inEvent->data.addDomain.interfaceIP.u.ipv4.addr, ifIP ) ); + break; + + case kDNSBrowserEventTypeAddDefaultDomain: + fprintf( stdout, "default domain \"%s\" added on interface 0x%08X (%s)\n", + inEvent->data.addDefaultDomain.domain, + (int) inEvent->data.addDefaultDomain.interfaceID, + IPv4ToString( inEvent->data.addDefaultDomain.interfaceIP.u.ipv4.addr, ifIP ) ); + break; + + case kDNSBrowserEventTypeRemoveDomain: + fprintf( stdout, "domain \"%s\" removed on interface 0x%08X (%s)\n", + inEvent->data.removeDomain.domain, + (int) inEvent->data.removeDomain.interfaceID, + IPv4ToString( inEvent->data.removeDomain.interfaceIP.u.ipv4.addr, ifIP ) ); + break; + + case kDNSBrowserEventTypeAddService: + fprintf( stdout, "service \"%s.%s%s\" added on interface 0x%08X (%s)\n", + inEvent->data.addService.name, + inEvent->data.addService.type, + inEvent->data.addService.domain, + (int) inEvent->data.addService.interfaceID, + IPv4ToString( inEvent->data.addService.interfaceIP.u.ipv4.addr, ifIP ) ); + break; + + case kDNSBrowserEventTypeRemoveService: + fprintf( stdout, "service \"%s.%s%s\" removed on interface 0x%08X (%s)\n", + inEvent->data.removeService.name, + inEvent->data.removeService.type, + inEvent->data.removeService.domain, + (int) inEvent->data.removeService.interfaceID, + IPv4ToString( inEvent->data.removeService.interfaceIP.u.ipv4.addr, ifIP ) ); + break; + + case kDNSBrowserEventTypeResolved: + { + const uint8_t * p; + const uint8_t * end; + int i; + + fprintf( stdout, "resolved \"%s.%s%s\" to %s:%u on interface 0x%08X (%s)%s\n", + inEvent->data.resolved->name, + inEvent->data.resolved->type, + inEvent->data.resolved->domain, + IPv4ToString( inEvent->data.resolved->address.u.ipv4.addr, ip ), + ( inEvent->data.resolved->address.u.ipv4.port.v8[ 0 ] << 8 ) | + inEvent->data.resolved->address.u.ipv4.port.v8[ 1 ], + (int) inEvent->data.resolved->interfaceID, + IPv4ToString( inEvent->data.resolved->interfaceIP.u.ipv4.addr, ifIP ), + ( inEvent->data.resolved->textRecordRawSize > 0 ) ? " with text:" : "" ); + + p = (const uint8_t *) inEvent->data.resolved->textRecordRaw; + end = p + inEvent->data.resolved->textRecordRawSize; + i = 0; + + if( gPrintTXTRecords ) + { + while( p < end ) + { + uint8_t size; + + size = *p++; + if( ( p + size ) > end ) + { + fprintf( stdout, "\n### MALFORMED TXT RECORD (length byte too big for record)\n\n" ); + break; + } + fprintf( stdout, "%5d (%3d bytes): \"%.*s\"\n", i, size, size, p ); + p += size; + ++i; + } + fprintf( stdout, "\n" ); + } + break; + } + + default: + break; + } +} + +//=========================================================================================================================== +// ResolverCallBack +//=========================================================================================================================== + +static void ResolverCallBack( void *inContext, DNSResolverRef inRef, DNSStatus inStatusCode, const DNSResolverEvent *inEvent ) +{ + char ifIP[ 32 ]; + char ip[ 32 ]; + + DNS_UNUSED( inContext ); + DNS_UNUSED( inRef ); + DNS_UNUSED( inStatusCode ); + + switch( inEvent->type ) + { + case kDNSResolverEventTypeResolved: + { + const uint8_t * p; + const uint8_t * end; + int i; + + fprintf( stdout, "resolved \"%s.%s%s\" to %s:%u on interface 0x%08X (%s)%s\n", + inEvent->data.resolved.name, + inEvent->data.resolved.type, + inEvent->data.resolved.domain, + IPv4ToString( inEvent->data.resolved.address.u.ipv4.addr, ip ), + ( inEvent->data.resolved.address.u.ipv4.port.v8[ 0 ] << 8 ) | + inEvent->data.resolved.address.u.ipv4.port.v8[ 1 ], + (int) inEvent->data.resolved.interfaceID, + IPv4ToString( inEvent->data.resolved.interfaceIP.u.ipv4.addr, ifIP ), + ( inEvent->data.resolved.textRecordRawSize > 0 ) ? " with text:" : "" ); + + p = (const uint8_t *) inEvent->data.resolved.textRecordRaw; + end = p + inEvent->data.resolved.textRecordRawSize; + i = 0; + + if( gPrintTXTRecords ) + { + while( p < end ) + { + uint8_t size; + + size = *p++; + if( ( p + size ) > end ) + { + fprintf( stdout, "\n### MALFORMED TXT RECORD (length byte too big for record)\n\n" ); + break; + } + fprintf( stdout, "%5d (%3d bytes): \"%.*s\"\n", i, size, size, p ); + p += size; + ++i; + } + fprintf( stdout, "\n" ); + } + break; + } + + case kDNSResolverEventTypeRelease: + break; + + default: + break; + } +} + +//=========================================================================================================================== +// RegistrationCallBack +//=========================================================================================================================== + +static void + RegistrationCallBack( + void * inContext, + DNSRegistrationRef inRef, + DNSStatus inStatusCode, + const DNSRegistrationEvent * inEvent ) +{ + DNS_UNUSED( inContext ); + DNS_UNUSED( inRef ); + DNS_UNUSED( inStatusCode ); + + switch( inEvent->type ) + { + case kDNSRegistrationEventTypeRelease: + break; + + case kDNSRegistrationEventTypeRegistered: + fprintf( stdout, "name registered and active\n" ); + break; + + case kDNSRegistrationEventTypeNameCollision: + fprintf( stdout, "name in use, please choose another name\n" ); + break; + + default: + break; + } +} + +//=========================================================================================================================== +// HostRegistrationCallBack +//=========================================================================================================================== + +static void + HostRegistrationCallBack( + void * inContext, + DNSHostRegistrationRef inRef, + DNSStatus inStatusCode, + void * inData ) +{ + DNS_UNUSED( inContext ); + DNS_UNUSED( inRef ); + DNS_UNUSED( inData ); + + if( inStatusCode == kDNSNoErr ) + { + fprintf( stdout, "host name registered and active\n" ); + } + else if( inStatusCode == kDNSNameConflictErr ) + { + fprintf( stdout, "host name in use, please choose another name\n" ); + } + else + { + fprintf( stdout, "unknown host registration status (%ld)\n", inStatusCode ); + } +} + +//=========================================================================================================================== +// EmulatedBrowserCallBack +//=========================================================================================================================== + +static void + EmulatedBrowserCallBack( + DNSServiceBrowserReplyResultType inResult, + const char * inName, + const char * inType, + const char * inDomain, + DNSServiceDiscoveryReplyFlags inFlags, + void * inContext ) +{ + DNS_UNUSED( inFlags ); + DNS_UNUSED( inContext ); + + if( inResult == DNSServiceBrowserReplyAddInstance ) + { + fprintf( stdout, "\"%s.%s%s\" service added emulated\n", inName, inType, inDomain ); + } + else if( inResult == DNSServiceBrowserReplyRemoveInstance ) + { + fprintf( stdout, "\"%s.%s%s\" service removed emulated\n", inName, inType, inDomain ); + } + else + { + fprintf( stdout, "### unknown emulated browser callback result (%d)\n", inResult ); + } +} + +//=========================================================================================================================== +// EmulatedDomainEnumerationCallBack +//=========================================================================================================================== + +static void + EmulatedDomainEnumerationCallBack( + DNSServiceDomainEnumerationReplyResultType inResult, + const char * inDomain, + DNSServiceDiscoveryReplyFlags inFlags, + void * inContext ) +{ + DNS_UNUSED( inFlags ); + DNS_UNUSED( inContext ); + + if( inResult == DNSServiceDomainEnumerationReplyAddDomain ) + { + fprintf( stdout, "\"%s\" domain added emulated\n", inDomain ); + } + else if( inResult == DNSServiceDomainEnumerationReplyAddDomainDefault ) + { + fprintf( stdout, "\"%s\" default domain added emulated\n", inDomain ); + } + else if( inResult == DNSServiceDomainEnumerationReplyRemoveDomain ) + { + fprintf( stdout, "\"%s\" domain removed emulated\n", inDomain ); + } + else + { + fprintf( stdout, "### unknown emulated domain enumeration callback result (%d)\n", inResult ); + } +} + +//=========================================================================================================================== +// EmulatedResolverCallBack +//=========================================================================================================================== + +static void + EmulatedResolverCallBack( + struct sockaddr * inInterfaceAddr, + struct sockaddr * inAddr, + const char * inTextRecord, + DNSServiceDiscoveryReplyFlags inFlags, + void * inContext ) +{ + struct sockaddr_in * ifSin4; + struct sockaddr_in * sin4; + char ifIP[ 64 ]; + char ip[ 64 ]; + + DNS_UNUSED( inFlags ); + DNS_UNUSED( inContext ); + + ifSin4 = (struct sockaddr_in *) inInterfaceAddr; + sin4 = (struct sockaddr_in *) inAddr; + + fprintf( stdout, "service resolved to %s:%d on interface %s with text \"%s\"\n", + IPv4ToString( *( (DNSOpaque32 *) &sin4->sin_addr.s_addr ), ip ), + ntohs( sin4->sin_port ), + IPv4ToString( *( (DNSOpaque32 *) &ifSin4->sin_addr.s_addr ), ifIP ), + inTextRecord ? inTextRecord : "" ); +} + +//=========================================================================================================================== +// EmulatedResolverCallBack +//=========================================================================================================================== + +static void EmulatedRegistrationCallBack( DNSServiceRegistrationReplyErrorType inResult, void *inContext ) +{ + DNS_UNUSED( inContext ); + + if( inResult == kDNSServiceDiscoveryNoError ) + { + fprintf( stdout, "service name registered successfully\n" ); + } + else + { + fprintf( stdout, "service registration failed( %d)\n", inResult ); + } +} + +//=========================================================================================================================== +// IPv4ToString +//=========================================================================================================================== + +static char * IPv4ToString( DNSOpaque32 inIP, char *outString ) +{ + sprintf( outString, "%u.%u.%u.%u", inIP.v8[ 0 ], inIP.v8[ 1 ], inIP.v8[ 2 ], inIP.v8[ 3 ] ); + return( outString ); +} diff --git a/mDNSWindows/Applications/DNSServiceTest/ToolPrefixWindows.h b/mDNSWindows/Applications/DNSServiceTest/ToolPrefixWindows.h new file mode 100644 index 0000000..eaa6a70 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceTest/ToolPrefixWindows.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ToolPrefixWindows.h,v $ +Revision 1.2 2003/08/20 07:06:34 bradley +Update to APSL 2.0. Updated change history to match other mDNSResponder files. + +Revision 1.1 2003/08/20 06:01:19 bradley +Prefix files for CodeWarrior Windows builds to set compile options. + +*/ + +#ifndef __TOOL_PREFIX_WINDOWS__ +#define __TOOL_PREFIX_WINDOWS__ + +#define DEBUG 0 + +#endif // __TOOL_PREFIX_WINDOWS__ diff --git a/mDNSWindows/Applications/DNSServiceTest/ToolPrefixWindowsDebug.h b/mDNSWindows/Applications/DNSServiceTest/ToolPrefixWindowsDebug.h new file mode 100644 index 0000000..1f76fc2 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceTest/ToolPrefixWindowsDebug.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + + Change History (most recent first): + +$Log: ToolPrefixWindowsDebug.h,v $ +Revision 1.2 2003/08/20 07:06:34 bradley +Update to APSL 2.0. Updated change history to match other mDNSResponder files. + +Revision 1.1 2003/08/20 06:01:19 bradley +Prefix files for CodeWarrior Windows builds to set compile options. + +*/ + +#ifndef __TOOL_PREFIX_WINDOWS_DEBUG__ +#define __TOOL_PREFIX_WINDOWS_DEBUG__ + +#define DEBUG 1 +#define MDNS_DEBUGMSGS 1 + +#endif // __TOOL_PREFIX_WINDOWS_DEBUG__ diff --git a/mDNSWindows/Applications/DNSServiceTest/ToolWin32.mcp b/mDNSWindows/Applications/DNSServiceTest/ToolWin32.mcp new file mode 100644 index 0000000..064aba0 Binary files /dev/null and b/mDNSWindows/Applications/DNSServiceTest/ToolWin32.mcp differ diff --git a/mDNSWindows/Applications/DNSServiceTest/ToolWin32VS2002.sln b/mDNSWindows/Applications/DNSServiceTest/ToolWin32VS2002.sln new file mode 100644 index 0000000..bc86b75 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceTest/ToolWin32VS2002.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 7.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tool", "ToolWin32VS2002.vcproj", "{F66EFE7E-50A6-44D4-87C7-742B303BA852}" +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + ConfigName.0 = all + ConfigName.1 = Debug + ConfigName.2 = Release + EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {F66EFE7E-50A6-44D4-87C7-742B303BA852}.all.ActiveCfg = all|Win32 + {F66EFE7E-50A6-44D4-87C7-742B303BA852}.all.Build.0 = all|Win32 + {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Debug.ActiveCfg = Debug|Win32 + {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Debug.Build.0 = Debug|Win32 + {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Release.ActiveCfg = Release|Win32 + {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/mDNSWindows/Applications/DNSServiceTest/ToolWin32VS2002.vcproj b/mDNSWindows/Applications/DNSServiceTest/ToolWin32VS2002.vcproj new file mode 100644 index 0000000..d5e1868 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceTest/ToolWin32VS2002.vcproj @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mDNSWindows/Applications/DNSServiceTest/ToolWin32VS2003.sln b/mDNSWindows/Applications/DNSServiceTest/ToolWin32VS2003.sln new file mode 100644 index 0000000..53a2ba2 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceTest/ToolWin32VS2003.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tool", "ToolWin32VS2003.vcproj", "{F66EFE7E-50A6-44D4-87C7-742B303BA852}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + all = all + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {F66EFE7E-50A6-44D4-87C7-742B303BA852}.all.ActiveCfg = all|Win32 + {F66EFE7E-50A6-44D4-87C7-742B303BA852}.all.Build.0 = all|Win32 + {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Debug.ActiveCfg = Debug|Win32 + {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Debug.Build.0 = Debug|Win32 + {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Release.ActiveCfg = Release|Win32 + {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/mDNSWindows/Applications/DNSServiceTest/ToolWin32VS2003.vcproj b/mDNSWindows/Applications/DNSServiceTest/ToolWin32VS2003.vcproj new file mode 100644 index 0000000..2349cb9 --- /dev/null +++ b/mDNSWindows/Applications/DNSServiceTest/ToolWin32VS2003.vcproj @@ -0,0 +1,205 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/ApplicationVS2002.sln b/mDNSWindows/Applications/RendezvousBrowser/Windows/ApplicationVS2002.sln deleted file mode 100644 index fe6ce77..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/ApplicationVS2002.sln +++ /dev/null @@ -1,24 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 7.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Application", "ApplicationVS2002.vcproj", "{EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}" -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - ConfigName.0 = All - ConfigName.1 = Debug - ConfigName.2 = Release - EndGlobalSection - GlobalSection(ProjectDependencies) = postSolution - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.All.ActiveCfg = All|Win32 - {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.All.Build.0 = All|Win32 - {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Debug.ActiveCfg = Debug|Win32 - {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Debug.Build.0 = Debug|Win32 - {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Release.ActiveCfg = Release|Win32 - {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/ApplicationVS2002.vcproj b/mDNSWindows/Applications/RendezvousBrowser/Windows/ApplicationVS2002.vcproj deleted file mode 100644 index 89316d2..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/ApplicationVS2002.vcproj +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/ApplicationVS2003.sln b/mDNSWindows/Applications/RendezvousBrowser/Windows/ApplicationVS2003.sln deleted file mode 100644 index 0bdb334..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/ApplicationVS2003.sln +++ /dev/null @@ -1,24 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Application", "ApplicationVS2003.vcproj", "{EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - All = All - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.All.ActiveCfg = All|Win32 - {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.All.Build.0 = All|Win32 - {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Debug.ActiveCfg = Debug|Win32 - {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Debug.Build.0 = Debug|Win32 - {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Release.ActiveCfg = Release|Win32 - {EDE4B529-4CF5-4A49-9B6F-C10F0EA24278}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/ApplicationVS2003.vcproj b/mDNSWindows/Applications/RendezvousBrowser/Windows/ApplicationVS2003.vcproj deleted file mode 100644 index 4f9b2bd..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/ApplicationVS2003.vcproj +++ /dev/null @@ -1,264 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/Resources/Application.ico b/mDNSWindows/Applications/RendezvousBrowser/Windows/Resources/Application.ico deleted file mode 100644 index a992327..0000000 Binary files a/mDNSWindows/Applications/RendezvousBrowser/Windows/Resources/Application.ico and /dev/null differ diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/Resources/Application.rc b/mDNSWindows/Applications/RendezvousBrowser/Windows/Resources/Application.rc deleted file mode 100644 index 1d9c2eb..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/Resources/Application.rc +++ /dev/null @@ -1,281 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "Resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "Resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "#define _AFX_NO_SPLITTER_RESOURCES\r\n" - "#define _AFX_NO_OLE_RESOURCES\r\n" - "#define _AFX_NO_TRACKER_RESOURCES\r\n" - "#define _AFX_NO_PROPERTY_RESOURCES\r\n" - "\r\n" - "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" - "#ifdef _WIN32\r\n" - "LANGUAGE 9, 1\r\n" - "#pragma code_page(1252)\r\n" - "#endif //_WIN32\r\n" - "#include ""Resources\\Application.rc2"" // non-Microsoft Visual C++ edited resources\r\n" - "#include ""afxres.rc"" // Standard components\r\n" - "#endif\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDR_MAIN_ICON ICON "Application.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_CHOOSER_DIALOG DIALOGEX 0, 0, 332, 252 -STYLE DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | - WS_SYSMENU -EXSTYLE WS_EX_APPWINDOW -CAPTION "Rendezvous Browser for Windows" -MENU IDR_CHOOSER_DIALOG_MENU -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - CONTROL "",IDC_CHOOSER_LIST,"SysListView32",LVS_REPORT | - LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | - LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,116,8,208,136 - CONTROL "",IDC_SERVICE_LIST,"SysListView32",LVS_REPORT | - LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | - LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,8,8,100,136 - CONTROL "",IDC_DOMAIN_LIST,"SysListView32",LVS_REPORT | - LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | - LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,8,152,100,92 - GROUPBOX "Information",IDC_STATIC,116,148,208,96 - RTEXT "Name:",IDC_STATIC,122,164,38,8 - LTEXT "My Device",IDC_INFO_NAME_TEXT,164,164,152,10,SS_SUNKEN - RTEXT "Text:",IDC_STATIC,122,203,38,8 - LTEXT "Information About My Device",IDC_INFO_TEXT_TEXT,164,203, - 152,34,SS_NOPREFIX | SS_SUNKEN - RTEXT "IP address:",IDC_STATIC,122,177,38,8 - LTEXT "123.124.125.126:1234",IDC_INFO_IP_TEXT,164,177,152,10, - SS_SUNKEN - RTEXT "Interface:",IDC_STATIC,122,190,38,8 - LTEXT "123.124.125.126",IDC_INFO_INTERFACE_TEXT,164,190,152,10, - SS_SUNKEN -END - -IDD_ABOUT_DIALOG DIALOGEX 0, 0, 244, 73 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION -CAPTION "About Rendezvous Browser" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - ICON IDR_MAIN_ICON,IDC_ABOUT_APP_ICON,12,12,20,20 - LTEXT "Rendezvous Browser for Windows",IDC_ABOUT_APP_NAME_TEXT, - 44,11,192,12 - LTEXT "Version 1.0d2",IDC_ABOUT_APP_VERSION_TEXT,44,25,192,8 - LTEXT "Copyright (C) 2002-2003 Apple Computer, Inc.", - IDC_ABOUT_COPYRIGHT_TEXT,4,60,156,8 - DEFPUSHBUTTON "OK",IDOK,192,52,44,14 -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,1 - PRODUCTVERSION 1,0,0,1 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "Quick & Dirty 1 day hack by Bob Bradley" - VALUE "CompanyName", "Apple Computer, Inc." - VALUE "FileDescription", "Rendezvous Browser for Windows" - VALUE "FileVersion", "1, 0, 0, 1" - VALUE "InternalName", "Rendezvous Browser for Windows" - VALUE "LegalCopyright", "Copyright (C) Apple Computer, Inc. 2001" - VALUE "OriginalFilename", "RendezvousBrowser.exe" - VALUE "ProductName", "Rendezvous Browser for Windows" - VALUE "ProductVersion", "1, 0, 0, 1" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDR_CHOOSER_DIALOG_MENU MENU -BEGIN - POPUP "File" - BEGIN - MENUITEM "Close &Window\tCtrl+W", ID_FILE_CLOSE - MENUITEM SEPARATOR - MENUITEM "Exit", ID_FILE_EXIT - END - POPUP "Help" - BEGIN - MENUITEM "About Rendezvous Browser...", ID_HELP_ABOUT - END -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Accelerator -// - -IDR_CHOOSER_DIALOG_MENU_ACCELERATORS ACCELERATORS -BEGIN - "S", ID_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT - "W", ID_FILE_CLOSE, VIRTKEY, CONTROL, NOINVERT -END - - -///////////////////////////////////////////////////////////////////////////// -// -// RT_MANIFEST -// - -1 RT_MANIFEST -BEGIN - 0x3f3c, 0x6d78, 0x206c, 0x6576, 0x7372, 0x6f69, 0x3d6e, 0x3122, 0x302e, - 0x2022, 0x6e65, 0x6f63, 0x6964, 0x676e, 0x223d, 0x5455, 0x2d46, 0x2238, - 0x7320, 0x6174, 0x646e, 0x6c61, 0x6e6f, 0x3d65, 0x7922, 0x7365, 0x3f22, - 0x203e, 0x0a0d, 0x613c, 0x7373, 0x6d65, 0x6c62, 0x2079, 0x0a0d, 0x2020, - 0x7820, 0x6c6d, 0x736e, 0x223d, 0x7275, 0x3a6e, 0x6373, 0x6568, 0x616d, - 0x2d73, 0x696d, 0x7263, 0x736f, 0x666f, 0x2d74, 0x6f63, 0x3a6d, 0x7361, - 0x2e6d, 0x3176, 0x2022, 0x0a0d, 0x2020, 0x6d20, 0x6e61, 0x6669, 0x7365, - 0x5674, 0x7265, 0x6973, 0x6e6f, 0x223d, 0x2e31, 0x2230, 0x0d3e, 0x3c0a, - 0x7361, 0x6573, 0x626d, 0x796c, 0x6449, 0x6e65, 0x6974, 0x7974, 0x0d20, - 0x200a, 0x2020, 0x7020, 0x6f72, 0x6563, 0x7373, 0x726f, 0x7241, 0x6863, - 0x7469, 0x6365, 0x7574, 0x6572, 0x223d, 0x3878, 0x2236, 0x0d20, 0x200a, - 0x2020, 0x7620, 0x7265, 0x6973, 0x6e6f, 0x223d, 0x2e35, 0x2e31, 0x2e30, - 0x2230, 0x0a0d, 0x2020, 0x2020, 0x7974, 0x6570, 0x223d, 0x6977, 0x336e, - 0x2232, 0x0a0d, 0x2020, 0x2020, 0x616e, 0x656d, 0x223d, 0x7041, 0x2e70, - 0x7865, 0x2265, 0x3e2f, 0x0a0d, 0x2020, 0x2020, 0x643c, 0x7365, 0x7263, - 0x7069, 0x6974, 0x6e6f, 0x413e, 0x7269, 0x6f50, 0x7472, 0x4120, 0x6d64, - 0x6e69, 0x5520, 0x6974, 0x696c, 0x7974, 0x2f3c, 0x6564, 0x6373, 0x6972, - 0x7470, 0x6f69, 0x3e6e, 0x0a0d, 0x2020, 0x2020, 0x643c, 0x7065, 0x6e65, - 0x6564, 0x636e, 0x3e79, 0x0a0d, 0x2020, 0x2020, 0x643c, 0x7065, 0x6e65, - 0x6564, 0x746e, 0x7341, 0x6573, 0x626d, 0x796c, 0x0d3e, 0x200a, 0x2020, - 0x3c20, 0x7361, 0x6573, 0x626d, 0x796c, 0x6449, 0x6e65, 0x6974, 0x7974, - 0x0a0d, 0x2020, 0x2020, 0x2020, 0x2020, 0x7420, 0x7079, 0x3d65, 0x7722, - 0x6e69, 0x3233, 0x0d22, 0x200a, 0x2020, 0x2020, 0x2020, 0x2020, 0x616e, - 0x656d, 0x223d, 0x694d, 0x7263, 0x736f, 0x666f, 0x2e74, 0x6957, 0x646e, - 0x776f, 0x2e73, 0x6f43, 0x6d6d, 0x6e6f, 0x432d, 0x6e6f, 0x7274, 0x6c6f, - 0x2273, 0x0a0d, 0x2020, 0x2020, 0x2020, 0x2020, 0x7620, 0x7265, 0x6973, - 0x6e6f, 0x223d, 0x2e36, 0x2e30, 0x2e30, 0x2230, 0x0a0d, 0x2020, 0x2020, - 0x2020, 0x2020, 0x7020, 0x6275, 0x696c, 0x4b63, 0x7965, 0x6f54, 0x656b, - 0x3d6e, 0x3622, 0x3935, 0x6235, 0x3436, 0x3431, 0x6334, 0x6663, 0x6431, - 0x2266, 0x0a0d, 0x2020, 0x2020, 0x2020, 0x2020, 0x6c20, 0x6e61, 0x7567, - 0x6761, 0x3d65, 0x2a22, 0x0d22, 0x200a, 0x2020, 0x2020, 0x2020, 0x2020, - 0x7270, 0x636f, 0x7365, 0x6f73, 0x4172, 0x6372, 0x6968, 0x6574, 0x7463, - 0x7275, 0x3d65, 0x7822, 0x3638, 0x2f22, 0x0d3e, 0x200a, 0x2020, 0x3c20, - 0x642f, 0x7065, 0x6e65, 0x6564, 0x746e, 0x7341, 0x6573, 0x626d, 0x796c, - 0x0d3e, 0x200a, 0x2020, 0x3c20, 0x642f, 0x7065, 0x6e65, 0x6564, 0x636e, - 0x3e79, 0x0a0d, 0x2f3c, 0x7361, 0x6573, 0x626d, 0x796c, 0x0d3e, "\012" -END - - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE -BEGIN - IDS_ABOUTBOX "&About Rendezvous Browser" - IDS_CHOOSER_DOMAIN_COLUMN_NAME "Domains" - IDP_SOCKETS_INIT_FAILED "Windows sockets initialization failed." - IDS_CHOOSER_SERVICE_COLUMN_NAME "Services" - IDS_CHOOSER_CHOOSER_NAME_COLUMN_NAME "Name" - IDS_CHOOSER_CHOOSER_IP_COLUMN_NAME "IP Address" -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// -#define _AFX_NO_SPLITTER_RESOURCES -#define _AFX_NO_OLE_RESOURCES -#define _AFX_NO_TRACKER_RESOURCES -#define _AFX_NO_PROPERTY_RESOURCES - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE 9, 1 -#pragma code_page(1252) -#endif //_WIN32 -#include "Resources\Application.rc2" // non-Microsoft Visual C++ edited resources -#include "afxres.rc" // Standard components -#endif - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/Resources/Application.rc2 b/mDNSWindows/Applications/RendezvousBrowser/Windows/Resources/Application.rc2 deleted file mode 100644 index bf1983f..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/Resources/Application.rc2 +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: Application.rc2,v $ -Revision 1.1 2003/08/21 02:06:46 bradley -Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. - -Revision 1.2 2003/08/20 07:06:34 bradley -Update to APSL 2.0. Updated change history to match other mDNSResponder files. - -Revision 1.1 2002/09/20 06:12:48 bradley -Rendezvous Browser for Windows - -*/ - -#ifdef APSTUDIO_INVOKED - #error this file is not editable by Microsoft Visual C++ -#endif //APSTUDIO_INVOKED diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/Resources/Resource.h b/mDNSWindows/Applications/RendezvousBrowser/Windows/Resources/Resource.h deleted file mode 100644 index 5329fc1..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/Resources/Resource.h +++ /dev/null @@ -1,45 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by Application.rc -// -#define IDS_ABOUTBOX 101 -#define IDS_CHOOSER_DOMAIN_COLUMN_NAME 102 -#define IDP_SOCKETS_INIT_FAILED 103 -#define IDS_CHOOSER_SERVICE_COLUMN_NAME 104 -#define IDS_CHOOSER_CHOOSER_NAME_COLUMN_NAME 105 -#define IDS_CHOOSER_CHOOSER_IP_COLUMN_NAME 106 -#define IDC_NAME_TEXT2 124 -#define IDC_INFO_NAME_TEXT 124 -#define IDC_DESCRIPTION_TEXT2 125 -#define IDC_INFO_TEXT_TEXT 125 -#define IDC_IP_TEXT2 126 -#define IDC_INFO_IP_TEXT 126 -#define IDC_IP_TEXT3 127 -#define IDC_INFO_INTERFACE_TEXT 127 -#define IDR_MAIN_ICON 128 -#define IDR_CHOOSER_DIALOG_MENU 136 -#define IDD_CHOOSER_DIALOG 143 -#define IDD_ABOUT_DIALOG 144 -#define IDR_CHOOSER_DIALOG_MENU_ACCELERATORS 146 -#define IDC_CHOOSER_LIST 1000 -#define IDC_SERVICE_LIST2 1001 -#define IDC_SERVICE_LIST 1001 -#define IDC_SERVICE_LIST3 1002 -#define IDC_DOMAIN_LIST 1002 -#define IDC_ABOUT_APP_NAME_TEXT 1105 -#define IDC_ABOUT_APP_VERSION_TEXT 1106 -#define IDC_ABOUT_COPYRIGHT_TEXT 1107 -#define IDC_ABOUT_APP_ICON 1108 -#define ID_FILE_EXIT 32771 -#define ID_HELP_ABOUT 32806 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 164 -#define _APS_NEXT_COMMAND_VALUE 32809 -#define _APS_NEXT_CONTROL_VALUE 1182 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/AboutDialog.cpp b/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/AboutDialog.cpp deleted file mode 100644 index cd8cafb..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/AboutDialog.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: AboutDialog.cpp,v $ -Revision 1.1 2003/08/21 02:06:47 bradley -Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. - -Revision 1.4 2003/08/12 19:56:28 cheshire -Update to APSL 2.0 - -Revision 1.3 2003/07/02 21:20:06 cheshire - Update copyright notices, etc., in source code comments - -Revision 1.2 2002/09/21 20:44:55 zarzycki -Added APSL info - -Revision 1.1 2002/09/20 06:12:49 bradley -Rendezvous Browser for Windows - -*/ - -#include - -#include "stdafx.h" - -#include "AboutDialog.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -//=========================================================================================================================== -// Message Map -//=========================================================================================================================== - -BEGIN_MESSAGE_MAP(AboutDialog, CDialog) - //{{AFX_MSG_MAP(AboutDialog) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -//=========================================================================================================================== -// AboutDialog -//=========================================================================================================================== - -AboutDialog::AboutDialog(CWnd* pParent /*=NULL*/) - : CDialog(AboutDialog::IDD, pParent) -{ - //{{AFX_DATA_INIT(AboutDialog) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - -//=========================================================================================================================== -// OnInitDialog -//=========================================================================================================================== - -BOOL AboutDialog::OnInitDialog() -{ - CDialog::OnInitDialog(); - return( true ); -} - -//=========================================================================================================================== -// DoDataExchange -//=========================================================================================================================== - -void AboutDialog::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(AboutDialog) - // NOTE: the ClassWizard will add DDX and DDV calls here - //}}AFX_DATA_MAP -} diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/AboutDialog.h b/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/AboutDialog.h deleted file mode 100644 index 11c9149..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/AboutDialog.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: AboutDialog.h,v $ -Revision 1.1 2003/08/21 02:06:47 bradley -Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. - -Revision 1.4 2003/08/12 19:56:28 cheshire -Update to APSL 2.0 - -Revision 1.3 2003/07/02 21:20:06 cheshire - Update copyright notices, etc., in source code comments - -Revision 1.2 2002/09/21 20:44:55 zarzycki -Added APSL info - -Revision 1.1 2002/09/20 06:12:50 bradley -Rendezvous Browser for Windows - -*/ - -#if !defined(AFX_ABOUTDIALOG_H__4B8A04B2_9735_4F4A_AFCA_15F85FB3D763__INCLUDED_) -#define AFX_ABOUTDIALOG_H__4B8A04B2_9735_4F4A_AFCA_15F85FB3D763__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include "Resource.h" - -//=========================================================================================================================== -// AboutDialog -//=========================================================================================================================== - -class AboutDialog : public CDialog -{ - public: - - // Creation/Deletion - - AboutDialog(CWnd* pParent = NULL); // standard constructor - - //{{AFX_DATA(AboutDialog) - enum { IDD = IDD_ABOUT_DIALOG }; - // NOTE: the ClassWizard will add data members here - //}}AFX_DATA - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(AboutDialog) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - protected: - - // Generated message map functions - //{{AFX_MSG(AboutDialog) - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_ABOUTDIALOG_H__4B8A04B2_9735_4F4A_AFCA_15F85FB3D763__INCLUDED_) diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/Application.cpp b/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/Application.cpp deleted file mode 100644 index 396b7e9..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/Application.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: Application.cpp,v $ -Revision 1.1 2003/08/21 02:06:47 bradley -Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. - -Revision 1.5 2003/08/12 19:56:28 cheshire -Update to APSL 2.0 - -Revision 1.4 2003/07/02 21:20:06 cheshire - Update copyright notices, etc., in source code comments - -Revision 1.3 2002/09/21 20:44:55 zarzycki -Added APSL info - -Revision 1.2 2002/09/20 08:37:34 bradley -Increased the DNS record cache from the default of 64 to 512 entries for larger networks. - -Revision 1.1 2002/09/20 06:12:51 bradley -Rendezvous Browser for Windows - -*/ - -#include - -#include "DNSServices.h" - -#include "Application.h" - -#include "ChooserDialog.h" - -#include "stdafx.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -//=========================================================================================================================== -// Message Map -//=========================================================================================================================== - -BEGIN_MESSAGE_MAP(Application, CWinApp) - //{{AFX_MSG_MAP(Application) - // NOTE - the ClassWizard will add and remove mapping macros here. - // DO NOT EDIT what you see in these blocks of generated code! - //}}AFX_MSG - ON_COMMAND(ID_HELP, CWinApp::OnHelp) -END_MESSAGE_MAP() - -//=========================================================================================================================== -// Globals -//=========================================================================================================================== - -Application gApp; - -//=========================================================================================================================== -// Application -//=========================================================================================================================== - -Application::Application( void ) -{ - // -} - -//=========================================================================================================================== -// InitInstance -//=========================================================================================================================== - -BOOL Application::InitInstance() -{ - DNSStatus err; - - // WinSock initialization. - - if( !AfxSocketInit() ) - { - AfxMessageBox( IDP_SOCKETS_INIT_FAILED ); - return( FALSE ); - } - - // Standard MFC initialization. - -#if( !defined( AFX_DEPRECATED ) ) - #ifdef _AFXDLL - Enable3dControls(); // Call this when using MFC in a shared DLL - #else - Enable3dControlsStatic(); // Call this when linking to MFC statically - #endif -#endif - - InitCommonControls(); - - // Set up DNS Services. - - err = DNSServicesInitialize( 0, 512 ); - assert( err == kDNSNoErr ); - - // Create the chooser dialog. - - ChooserDialog * dialog; - - m_pMainWnd = NULL; - dialog = new ChooserDialog; - dialog->Create( IDD_CHOOSER_DIALOG ); - m_pMainWnd = dialog; - dialog->ShowWindow( SW_SHOW ); - - return( true ); -} - -//=========================================================================================================================== -// ExitInstance -//=========================================================================================================================== - -int Application::ExitInstance( void ) -{ - // Clean up DNS Services. - - DNSServicesFinalize(); - return( 0 ); -} diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/Application.h b/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/Application.h deleted file mode 100644 index e174e4f..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/Application.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: Application.h,v $ -Revision 1.1 2003/08/21 02:06:47 bradley -Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. - -Revision 1.4 2003/08/12 19:56:28 cheshire -Update to APSL 2.0 - -Revision 1.3 2003/07/02 21:20:06 cheshire - Update copyright notices, etc., in source code comments - -Revision 1.2 2002/09/21 20:44:55 zarzycki -Added APSL info - -Revision 1.1 2002/09/20 06:12:51 bradley -Rendezvous Browser for Windows - -*/ - -#if !defined(AFX_ADMIN_H__8663733F_6A15_439F_B568_F5A0125CD572__INCLUDED_) -#define AFX_ADMIN_H__8663733F_6A15_439F_B568_F5A0125CD572__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include "stdafx.h" - -#ifndef __AFXWIN_H__ - #error include 'stdafx.h' before including this file for PCH -#endif - -#include "Resource.h" - -//=========================================================================================================================== -// Globals -//=========================================================================================================================== - -extern class Application gApp; - -//=========================================================================================================================== -// Application -//=========================================================================================================================== - -class Application : public CWinApp -{ - public: - - // Creation/Deletion - - Application(); - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(Application) - public: - virtual BOOL InitInstance(); - virtual int ExitInstance( void ); - //}}AFX_VIRTUAL - - //{{AFX_MSG(Application) - // NOTE - the ClassWizard will add and remove member functions here. - // DO NOT EDIT what you see in these blocks of generated code ! - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_ADMIN_H__8663733F_6A15_439F_B568_F5A0125CD572__INCLUDED_) diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/ChooserDialog.cpp b/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/ChooserDialog.cpp deleted file mode 100644 index ddd81f9..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/ChooserDialog.cpp +++ /dev/null @@ -1,1171 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: ChooserDialog.cpp,v $ -Revision 1.1 2003/08/21 02:06:47 bradley -Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. - -Revision 1.7 2003/08/20 06:45:56 bradley -Updated for IP address changes in DNSServices. Added support for browsing for Xserve RAID. - -Revision 1.6 2003/08/12 19:56:28 cheshire -Update to APSL 2.0 - -Revision 1.5 2003/07/13 01:03:55 cheshire -Diffs provided by Bob Bradley to provide provide proper display of Unicode names - -Revision 1.4 2003/07/02 21:20:06 cheshire - Update copyright notices, etc., in source code comments - -Revision 1.3 2002/09/21 20:44:55 zarzycki -Added APSL info - -Revision 1.2 2002/09/20 08:39:21 bradley -Make sure each resolved item matches the selected service type to handle resolved that may have -been queued up on the Windows Message Loop. Reduce column to fit when scrollbar is present. - -Revision 1.1 2002/09/20 06:12:52 bradley -Rendezvous Browser for Windows - -*/ - -#include -#include -#include -#include -#include - -#include -#include - -#include "stdafx.h" - -#include "DNSServices.h" - -#include "Application.h" -#include "AboutDialog.h" -#include "Resource.h" - -#include "ChooserDialog.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -#if 0 -#pragma mark == Constants == -#endif - -//=========================================================================================================================== -// Constants -//=========================================================================================================================== - -// Menus - -enum -{ - kChooserMenuIndexFile = 0, - kChooserMenuIndexHelp = 1 -}; - -// Domain List - -#define kDomainListDefaultDomainColumnIndex 0 -#define kDomainListDefaultDomainColumnWidth 140 - -// Service List - -#define kServiceListDefaultServiceColumnIndex 0 -#define kServiceListDefaultServiceColumnWidth 140 - -// Chooser List - -#define kChooserListDefaultNameColumnIndex 0 -#define kChooserListDefaultNameColumnWidth 162 - -#define kChooserListDefaultIPColumnIndex 1 -#define kChooserListDefaultIPColumnWidth 126 - -// Windows User Messages - -#define WM_USER_DOMAIN_ADD ( WM_USER + 0x100 ) -#define WM_USER_DOMAIN_REMOVE ( WM_USER + 0x101 ) -#define WM_USER_SERVICE_ADD ( WM_USER + 0x102 ) -#define WM_USER_SERVICE_REMOVE ( WM_USER + 0x103 ) -#define WM_USER_RESOLVE ( WM_USER + 0x104 ) - -#if 0 -#pragma mark == Constants - Service Table == -#endif - -//=========================================================================================================================== -// Constants - Service Table -//=========================================================================================================================== - -struct KnownServiceEntry -{ - const char * serviceType; - const char * description; - const char * urlScheme; - bool useText; -}; - -static const KnownServiceEntry kKnownServiceTable[] = -{ - { "_airport._tcp.", "AirPort Base Station", "acp://", false }, - { "_afpovertcp._tcp.", "AppleShare Server", "afp://", false }, - { "_ftp._tcp.", "File Transfer (FTP)", "ftp://", false }, - { "_ichat._tcp.", "iChat", "ichat://", false }, - { "_printer._tcp.", "Printer (LPD)", "ldp://", false }, - { "_eppc._tcp.", "Remote AppleEvents", "eppc://", false }, - { "_ssh._tcp.", "Secure Shell (SSH)", "ssh://", false }, - { "_tftp._tcp.", "Trivial File Transfer (TFTP)", "tftp://", false }, - { "_http._tcp.", "Web Server (HTTP)", "http://", true }, - { "_smb._tcp.", "Windows File Sharing", "smb://", false }, - { "_xserveraid._tcp.", "Xserve RAID", "xsr://", false }, - { NULL, NULL, NULL, false }, -}; - -#if 0 -#pragma mark == Structures == -#endif - -//=========================================================================================================================== -// Structures -//=========================================================================================================================== - -struct DomainEventInfo -{ - DNSBrowserEventType eventType; - CString domain; - DNSNetworkAddress ifIP; -}; - -struct ServiceEventInfo -{ - DNSBrowserEventType eventType; - std::string name; - std::string type; - std::string domain; - DNSNetworkAddress ifIP; -}; - -#if 0 -#pragma mark == Prototypes == -#endif - -//=========================================================================================================================== -// Prototypes -//=========================================================================================================================== - -static void - BrowserCallBack( - void * inContext, - DNSBrowserRef inRef, - DNSStatus inStatusCode, - const DNSBrowserEvent * inEvent ); - -static char * DNSNetworkAddressToString( const DNSNetworkAddress *inAddr, char *outString ); - -static DWORD UTF8StringToStringObject( const char *inUTF8, CString &inObject ); - -#if 0 -#pragma mark == Message Map == -#endif - -//=========================================================================================================================== -// Message Map -//=========================================================================================================================== - -BEGIN_MESSAGE_MAP(ChooserDialog, CDialog) - //{{AFX_MSG_MAP(ChooserDialog) - ON_WM_SYSCOMMAND() - ON_NOTIFY(LVN_ITEMCHANGED, IDC_DOMAIN_LIST, OnDomainListChanged) - ON_NOTIFY(LVN_ITEMCHANGED, IDC_SERVICE_LIST, OnServiceListChanged) - ON_NOTIFY(LVN_ITEMCHANGED, IDC_CHOOSER_LIST, OnChooserListChanged) - ON_NOTIFY(NM_DBLCLK, IDC_CHOOSER_LIST, OnChooserListDoubleClick) - ON_COMMAND(ID_HELP_ABOUT, OnAbout) - ON_WM_INITMENUPOPUP() - ON_WM_ACTIVATE() - ON_COMMAND(ID_FILE_CLOSE, OnFileClose) - ON_COMMAND(ID_FILE_EXIT, OnExit) - ON_WM_CLOSE() - ON_WM_NCDESTROY() - //}}AFX_MSG_MAP - ON_MESSAGE( WM_USER_DOMAIN_ADD, OnDomainAdd ) - ON_MESSAGE( WM_USER_DOMAIN_REMOVE, OnDomainRemove ) - ON_MESSAGE( WM_USER_SERVICE_ADD, OnServiceAdd ) - ON_MESSAGE( WM_USER_SERVICE_REMOVE, OnServiceRemove ) - ON_MESSAGE( WM_USER_RESOLVE, OnResolve ) -END_MESSAGE_MAP() - -#if 0 -#pragma mark == Routines == -#endif - -//=========================================================================================================================== -// ChooserDialog -//=========================================================================================================================== - -ChooserDialog::ChooserDialog( CWnd *inParent ) - : CDialog( ChooserDialog::IDD, inParent) -{ - //{{AFX_DATA_INIT(ChooserDialog) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT - - // Load menu accelerator table. - - mMenuAcceleratorTable = ::LoadAccelerators( AfxGetInstanceHandle(), MAKEINTRESOURCE( IDR_CHOOSER_DIALOG_MENU_ACCELERATORS ) ); - assert( mMenuAcceleratorTable ); - - mBrowser = NULL; - mIsServiceBrowsing = false; -} - -//=========================================================================================================================== -// ~ChooserDialog -//=========================================================================================================================== - -ChooserDialog::~ChooserDialog( void ) -{ - if( mBrowser ) - { - DNSStatus err; - - err = DNSBrowserRelease( mBrowser, 0 ); - assert( err == kDNSNoErr ); - } -} - -//=========================================================================================================================== -// DoDataExchange -//=========================================================================================================================== - -void ChooserDialog::DoDataExchange( CDataExchange *pDX ) -{ - CDialog::DoDataExchange(pDX); - - //{{AFX_DATA_MAP(ChooserDialog) - DDX_Control(pDX, IDC_SERVICE_LIST, mServiceList); - DDX_Control(pDX, IDC_DOMAIN_LIST, mDomainList); - DDX_Control(pDX, IDC_CHOOSER_LIST, mChooserList); - //}}AFX_DATA_MAP -} - -//=========================================================================================================================== -// OnInitDialog -//=========================================================================================================================== - -BOOL ChooserDialog::OnInitDialog( void ) -{ - BOOL result; - CString tempString; - DNSStatus err; - - // Initialize our parent. - - CDialog::OnInitDialog(); - - // Set up the Domain List. - - result = tempString.LoadString( IDS_CHOOSER_DOMAIN_COLUMN_NAME ); - assert( result ); - mDomainList.InsertColumn( 0, tempString, LVCFMT_LEFT, kDomainListDefaultDomainColumnWidth ); - - // Set up the Service List. - - result = tempString.LoadString( IDS_CHOOSER_SERVICE_COLUMN_NAME ); - assert( result ); - mServiceList.InsertColumn( 0, tempString, LVCFMT_LEFT, kServiceListDefaultServiceColumnWidth ); - - PopulateServicesList(); - - // Set up the Chooser List. - - result = tempString.LoadString( IDS_CHOOSER_CHOOSER_NAME_COLUMN_NAME ); - assert( result ); - mChooserList.InsertColumn( 0, tempString, LVCFMT_LEFT, kChooserListDefaultNameColumnWidth ); - - result = tempString.LoadString( IDS_CHOOSER_CHOOSER_IP_COLUMN_NAME ); - assert( result ); - mChooserList.InsertColumn( 1, tempString, LVCFMT_LEFT, kChooserListDefaultIPColumnWidth ); - - // Set up the other controls. - - UpdateInfoDisplay(); - - // Start browsing for domains. - - err = DNSBrowserCreate( 0, BrowserCallBack, this, &mBrowser ); - assert( err == kDNSNoErr ); - - err = DNSBrowserStartDomainSearch( mBrowser, 0 ); - assert( err == kDNSNoErr ); - - return( true ); -} - -//=========================================================================================================================== -// OnFileClose -//=========================================================================================================================== - -void ChooserDialog::OnFileClose() -{ - OnClose(); -} - -//=========================================================================================================================== -// OnActivate -//=========================================================================================================================== - -void ChooserDialog::OnActivate( UINT nState, CWnd* pWndOther, BOOL bMinimized ) -{ - // Always make the active window the "main" window so modal dialogs work better and the app quits after closing - // the last window. - - gApp.m_pMainWnd = this; - - CDialog::OnActivate(nState, pWndOther, bMinimized); -} - -//=========================================================================================================================== -// PostNcDestroy -//=========================================================================================================================== - -void ChooserDialog::PostNcDestroy() -{ - // Call the base class to do the normal cleanup. - - delete this; -} - -//=========================================================================================================================== -// PreTranslateMessage -//=========================================================================================================================== - -BOOL ChooserDialog::PreTranslateMessage(MSG* pMsg) -{ - BOOL result; - - result = false; - assert( mMenuAcceleratorTable ); - if( mMenuAcceleratorTable ) - { - result = ::TranslateAccelerator( m_hWnd, mMenuAcceleratorTable, pMsg ); - } - if( !result ) - { - result = CDialog::PreTranslateMessage( pMsg ); - } - return( result ); -} - -//=========================================================================================================================== -// OnInitMenuPopup -//=========================================================================================================================== - -void ChooserDialog::OnInitMenuPopup( CMenu *pPopupMenu, UINT nIndex, BOOL bSysMenu ) -{ - CDialog::OnInitMenuPopup( pPopupMenu, nIndex, bSysMenu ); - - switch( nIndex ) - { - case kChooserMenuIndexFile: - break; - - case kChooserMenuIndexHelp: - break; - - default: - break; - } -} - -//=========================================================================================================================== -// OnExit -//=========================================================================================================================== - -void ChooserDialog::OnExit() -{ - AfxPostQuitMessage( 0 ); -} - -//=========================================================================================================================== -// OnAbout -//=========================================================================================================================== - -void ChooserDialog::OnAbout() -{ - AboutDialog dialog; - - dialog.DoModal(); -} - -//=========================================================================================================================== -// OnSysCommand -//=========================================================================================================================== - -void ChooserDialog::OnSysCommand( UINT inID, LPARAM inParam ) -{ - CDialog::OnSysCommand( inID, inParam ); -} - -//=========================================================================================================================== -// OnClose -//=========================================================================================================================== - -void ChooserDialog::OnClose() -{ - StopBrowsing(); - - gApp.m_pMainWnd = this; - DestroyWindow(); -} - -//=========================================================================================================================== -// OnNcDestroy -//=========================================================================================================================== - -void ChooserDialog::OnNcDestroy() -{ - gApp.m_pMainWnd = this; - - CDialog::OnNcDestroy(); -} - -//=========================================================================================================================== -// OnDomainListChanged -//=========================================================================================================================== - -void ChooserDialog::OnDomainListChanged( NMHDR *pNMHDR, LRESULT *pResult ) -{ - UNUSED_ALWAYS( pNMHDR ); - - // Domain list changes have similar effects to service list changes so reuse that code path by calling it here. - - OnServiceListChanged( NULL, NULL ); - - *pResult = 0; -} - -//=========================================================================================================================== -// OnServiceListChanged -//=========================================================================================================================== - -void ChooserDialog::OnServiceListChanged( NMHDR *pNMHDR, LRESULT *pResult ) -{ - int selectedType; - int selectedDomain; - - UNUSED_ALWAYS( pNMHDR ); - - // Stop any existing service search. - - StopBrowsing(); - - // If a domain and service type are selected, start searching for the service type on the domain. - - selectedType = mServiceList.GetNextItem( -1, LVNI_SELECTED ); - selectedDomain = mDomainList.GetNextItem( -1, LVNI_SELECTED ); - - if( ( selectedType >= 0 ) && ( selectedDomain >= 0 ) ) - { - CString type; - CString domain; - - type = mServiceTypes[ selectedType ].serviceType.c_str(); - domain = mDomainList.GetItemText( selectedDomain, 0 ); - - StartBrowsing( type, domain ); - } - - if( pResult ) - { - *pResult = 0; - } -} - -//=========================================================================================================================== -// OnChooserListChanged -//=========================================================================================================================== - -void ChooserDialog::OnChooserListChanged( NMHDR *pNMHDR, LRESULT *pResult ) -{ - UNUSED_ALWAYS( pNMHDR ); - - UpdateInfoDisplay(); - *pResult = 0; -} - -//=========================================================================================================================== -// OnChooserListDoubleClick -//=========================================================================================================================== - -void ChooserDialog::OnChooserListDoubleClick( NMHDR *pNMHDR, LRESULT *pResult ) -{ - int selectedItem; - - UNUSED_ALWAYS( pNMHDR ); - - // Display the service instance if it is selected. Otherwise, clear all the info. - - selectedItem = mChooserList.GetNextItem( -1, LVNI_SELECTED ); - if( selectedItem >= 0 ) - { - ServiceInstanceInfo * p; - CString url; - const KnownServiceEntry * service; - - assert( selectedItem < (int) mServiceInstances.size() ); - p = &mServiceInstances[ selectedItem ]; - - // Search for a known service type entry that matches. - - for( service = kKnownServiceTable; service->serviceType; ++service ) - { - if( p->type == service->serviceType ) - { - break; - } - } - if( service->serviceType ) - { - // Create a URL representing the service instance. Special case for SMB (no port number). - - if( strcmp( service->serviceType, "_smb._tcp" ) == 0 ) - { - url.Format( "%s%s/", service->urlScheme, (const char *) p->ip.c_str() ); - } - else - { - const char * text; - - text = service->useText ? p->text.c_str() : ""; - url.Format( "%s%s/%s", service->urlScheme, (const char *) p->ip.c_str(), text ); - } - - // Let the system open the URL in the correct app. - - ShellExecute( NULL, "open", url, "", "c:\\", SW_SHOWNORMAL ); - } - } - *pResult = 0; -} - -//=========================================================================================================================== -// OnCancel -//=========================================================================================================================== - -void ChooserDialog::OnCancel() -{ - // Do nothing. -} - -//=========================================================================================================================== -// PopulateServicesList -//=========================================================================================================================== - -void ChooserDialog::PopulateServicesList( void ) -{ - ServiceTypeVector::iterator i; - CString name; - - // Add a fixed list of known services. - - if( mServiceTypes.empty() ) - { - const KnownServiceEntry * service; - - for( service = kKnownServiceTable; service->serviceType; ++service ) - { - ServiceTypeInfo info; - - info.serviceType = service->serviceType; - info.description = service->description; - info.urlScheme = service->urlScheme; - mServiceTypes.push_back( info ); - } - } - - // Add each service to the list. - - for( i = mServiceTypes.begin(); i != mServiceTypes.end(); ++i ) - { - UTF8StringToStringObject( ( *i ).description.c_str(), name ); - mServiceList.InsertItem( mServiceList.GetItemCount(), name ); - } - - // Select the first service type by default. - - if( !mServiceTypes.empty() ) - { - mServiceList.SetItemState( 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED ); - } -} - -//=========================================================================================================================== -// UpdateInfoDisplay -//=========================================================================================================================== - -void ChooserDialog::UpdateInfoDisplay( void ) -{ - int selectedItem; - std::string name; - CString s; - std::string ip; - std::string ifIP; - std::string text; - CWnd * item; - - // Display the service instance if it is selected. Otherwise, clear all the info. - - selectedItem = mChooserList.GetNextItem( -1, LVNI_SELECTED ); - if( selectedItem >= 0 ) - { - ServiceInstanceInfo * p; - - assert( selectedItem < (int) mServiceInstances.size() ); - p = &mServiceInstances[ selectedItem ]; - - name = p->name; - ip = p->ip; - ifIP = p->ifIP; - text = p->text; - - // Sync up the list items with the actual data (IP address may change). - - mChooserList.SetItemText( selectedItem, 1, ip.c_str() ); - } - - // Name - - item = (CWnd *) this->GetDlgItem( IDC_INFO_NAME_TEXT ); - assert( item ); - UTF8StringToStringObject( name.c_str(), s ); - item->SetWindowText( s ); - - // IP - - item = (CWnd *) this->GetDlgItem( IDC_INFO_IP_TEXT ); - assert( item ); - item->SetWindowText( ip.c_str() ); - - // Interface - - item = (CWnd *) this->GetDlgItem( IDC_INFO_INTERFACE_TEXT ); - assert( item ); - item->SetWindowText( ifIP.c_str() ); - - // Text - - if( text.size() > 255 ) - { - text.resize( 255 ); - } - item = (CWnd *) this->GetDlgItem( IDC_INFO_TEXT_TEXT ); - assert( item ); - item->SetWindowText( text.c_str() ); -} - -#if 0 -#pragma mark - -#endif - -//=========================================================================================================================== -// OnDomainAdd -//=========================================================================================================================== - -LONG ChooserDialog::OnDomainAdd( WPARAM inWParam, LPARAM inLParam ) -{ - DomainEventInfo * p; - std::auto_ptr < DomainEventInfo > pAutoPtr; - int n; - int i; - CString domain; - CString s; - bool found; - - UNUSED_ALWAYS( inWParam ); - - assert( inLParam ); - p = reinterpret_cast ( inLParam ); - pAutoPtr.reset( p ); - - // Search to see if we already know about this domain. If not, add it to the list. - - found = false; - domain = p->domain; - n = mDomainList.GetItemCount(); - for( i = 0; i < n; ++i ) - { - s = mDomainList.GetItemText( i, 0 ); - if( s == domain ) - { - found = true; - break; - } - } - if( !found ) - { - int selectedItem; - - mDomainList.InsertItem( n, domain ); - - // If no domains are selected and the domain being added is a default domain, select it. - - selectedItem = mDomainList.GetNextItem( -1, LVNI_SELECTED ); - if( ( selectedItem < 0 ) && ( p->eventType == kDNSBrowserEventTypeAddDefaultDomain ) ) - { - mDomainList.SetItemState( n, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED ); - } - } - return( 0 ); -} - -//=========================================================================================================================== -// OnDomainRemove -//=========================================================================================================================== - -LONG ChooserDialog::OnDomainRemove( WPARAM inWParam, LPARAM inLParam ) -{ - DomainEventInfo * p; - std::auto_ptr < DomainEventInfo > pAutoPtr; - int n; - int i; - CString domain; - CString s; - bool found; - - UNUSED_ALWAYS( inWParam ); - - assert( inLParam ); - p = reinterpret_cast ( inLParam ); - pAutoPtr.reset( p ); - - // Search to see if we know about this domain. If so, remove it from the list. - - found = false; - domain = p->domain; - n = mDomainList.GetItemCount(); - for( i = 0; i < n; ++i ) - { - s = mDomainList.GetItemText( i, 0 ); - if( s == domain ) - { - found = true; - break; - } - } - if( found ) - { - mDomainList.DeleteItem( i ); - } - return( 0 ); -} - -//=========================================================================================================================== -// OnServiceAdd -//=========================================================================================================================== - -LONG ChooserDialog::OnServiceAdd( WPARAM inWParam, LPARAM inLParam ) -{ - ServiceEventInfo * p; - std::auto_ptr < ServiceEventInfo > pAutoPtr; - - UNUSED_ALWAYS( inWParam ); - - assert( inLParam ); - p = reinterpret_cast ( inLParam ); - pAutoPtr.reset( p ); - - return( 0 ); -} - -//=========================================================================================================================== -// OnServiceRemove -//=========================================================================================================================== - -LONG ChooserDialog::OnServiceRemove( WPARAM inWParam, LPARAM inLParam ) -{ - ServiceEventInfo * p; - std::auto_ptr < ServiceEventInfo > pAutoPtr; - bool found; - int n; - int i; - - UNUSED_ALWAYS( inWParam ); - - assert( inLParam ); - p = reinterpret_cast ( inLParam ); - pAutoPtr.reset( p ); - - // Search to see if we know about this service instance. If so, remove it from the list. - - found = false; - n = (int) mServiceInstances.size(); - for( i = 0; i < n; ++i ) - { - ServiceInstanceInfo * q; - - // If the name, type, domain, and interface match, treat it as the same service instance. - - q = &mServiceInstances[ i ]; - if( ( p->name == q->name ) && - ( p->type == q->type ) && - ( p->domain == q->domain ) ) - { - found = true; - break; - } - } - if( found ) - { - mChooserList.DeleteItem( i ); - assert( i < (int) mServiceInstances.size() ); - mServiceInstances.erase( mServiceInstances.begin() + i ); - } - return( 0 ); -} - -//=========================================================================================================================== -// OnResolve -//=========================================================================================================================== - -LONG ChooserDialog::OnResolve( WPARAM inWParam, LPARAM inLParam ) -{ - ServiceInstanceInfo * p; - std::auto_ptr < ServiceInstanceInfo > pAutoPtr; - int selectedType; - int n; - int i; - bool found; - - UNUSED_ALWAYS( inWParam ); - - assert( inLParam ); - p = reinterpret_cast ( inLParam ); - pAutoPtr.reset( p ); - - // Make sure it is for an item of the correct type. This handles any resolves that may have been queued up. - - selectedType = mServiceList.GetNextItem( -1, LVNI_SELECTED ); - assert( selectedType >= 0 ); - if( selectedType >= 0 ) - { - assert( selectedType <= (int) mServiceTypes.size() ); - if( p->type != mServiceTypes[ selectedType ].serviceType ) - { - goto exit; - } - } - - // Search to see if we know about this service instance. If so, update its info. Otherwise, add it to the list. - - found = false; - n = (int) mServiceInstances.size(); - for( i = 0; i < n; ++i ) - { - ServiceInstanceInfo * q; - - // If the name, type, domain, and interface matches, treat it as the same service instance. - - q = &mServiceInstances[ i ]; - if( ( p->name == q->name ) && - ( p->type == q->type ) && - ( p->domain == q->domain ) && - ( p->ifIP == q->ifIP ) ) - { - found = true; - break; - } - } - if( found ) - { - mServiceInstances[ i ] = *p; - } - else - { - CString s; - - mServiceInstances.push_back( *p ); - UTF8StringToStringObject( p->name.c_str(), s ); - mChooserList.InsertItem( n, s ); - mChooserList.SetItemText( n, 1, p->ip.c_str() ); - - // If this is the only item, select it. - - if( n == 0 ) - { - mChooserList.SetItemState( n, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED ); - } - } - UpdateInfoDisplay(); - -exit: - return( 0 ); -} - -//=========================================================================================================================== -// StartBrowsing -//=========================================================================================================================== - -void ChooserDialog::StartBrowsing( const char *inType, const char *inDomain ) -{ - DNSStatus err; - - assert( mServiceInstances.empty() ); - assert( mChooserList.GetItemCount() == 0 ); - assert( !mIsServiceBrowsing ); - - mChooserList.DeleteAllItems(); - mServiceInstances.clear(); - - mIsServiceBrowsing = true; - err = DNSBrowserStartServiceSearch( mBrowser, kDNSBrowserFlagAutoResolve, inType, inDomain ); - assert( err == kDNSNoErr ); -} - -//=========================================================================================================================== -// StopBrowsing -//=========================================================================================================================== - -void ChooserDialog::StopBrowsing( void ) -{ - // If searching, stop. - - if( mIsServiceBrowsing ) - { - DNSStatus err; - - mIsServiceBrowsing = false; - err = DNSBrowserStopServiceSearch( mBrowser, 0 ); - assert( err == kDNSNoErr ); - } - - // Remove all service instances. - - mChooserList.DeleteAllItems(); - assert( mChooserList.GetItemCount() == 0 ); - mServiceInstances.clear(); - assert( mServiceInstances.empty() ); - UpdateInfoDisplay(); -} - -#if 0 -#pragma mark - -#endif - -//=========================================================================================================================== -// BrowserCallBack -//=========================================================================================================================== - -static void - BrowserCallBack( - void * inContext, - DNSBrowserRef inRef, - DNSStatus inStatusCode, - const DNSBrowserEvent * inEvent ) -{ - ChooserDialog * dialog; - UINT message; - BOOL posted; - - UNUSED_ALWAYS( inStatusCode ); - UNUSED_ALWAYS( inRef ); - - // Check parameters. - - assert( inContext ); - dialog = reinterpret_cast ( inContext ); - - try - { - switch( inEvent->type ) - { - case kDNSBrowserEventTypeRelease: - break; - - // Domains - - case kDNSBrowserEventTypeAddDomain: - case kDNSBrowserEventTypeAddDefaultDomain: - case kDNSBrowserEventTypeRemoveDomain: - { - DomainEventInfo * domain; - std::auto_ptr < DomainEventInfo > domainAutoPtr; - - domain = new DomainEventInfo; - domainAutoPtr.reset( domain ); - - domain->eventType = inEvent->type; - domain->domain = inEvent->data.addDomain.domain; - domain->ifIP = inEvent->data.addDomain.interfaceIP; - - message = ( inEvent->type == kDNSBrowserEventTypeRemoveDomain ) ? WM_USER_DOMAIN_REMOVE : WM_USER_DOMAIN_ADD; - posted = ::PostMessage( dialog->GetSafeHwnd(), message, 0, (LPARAM) domain ); - assert( posted ); - if( posted ) - { - domainAutoPtr.release(); - } - break; - } - - // Services - - case kDNSBrowserEventTypeAddService: - case kDNSBrowserEventTypeRemoveService: - { - ServiceEventInfo * service; - std::auto_ptr < ServiceEventInfo > serviceAutoPtr; - - service = new ServiceEventInfo; - serviceAutoPtr.reset( service ); - - service->eventType = inEvent->type; - service->name = inEvent->data.addService.name; - service->type = inEvent->data.addService.type; - service->domain = inEvent->data.addService.domain; - service->ifIP = inEvent->data.addService.interfaceIP; - - message = ( inEvent->type == kDNSBrowserEventTypeAddService ) ? WM_USER_SERVICE_ADD : WM_USER_SERVICE_REMOVE; - posted = ::PostMessage( dialog->GetSafeHwnd(), message, 0, (LPARAM) service ); - assert( posted ); - if( posted ) - { - serviceAutoPtr.release(); - } - break; - } - - // Resolves - - case kDNSBrowserEventTypeResolved: - { - ServiceInstanceInfo * serviceInstance; - std::auto_ptr < ServiceInstanceInfo > serviceInstanceAutoPtr; - char s[ 32 ]; - - serviceInstance = new ServiceInstanceInfo; - serviceInstanceAutoPtr.reset( serviceInstance ); - - serviceInstance->name = inEvent->data.resolved->name; - serviceInstance->type = inEvent->data.resolved->type; - serviceInstance->domain = inEvent->data.resolved->domain; - serviceInstance->ip = DNSNetworkAddressToString( &inEvent->data.resolved->address, s ); - serviceInstance->ifIP = DNSNetworkAddressToString( &inEvent->data.resolved->interfaceIP, s ); - serviceInstance->text = inEvent->data.resolved->textRecord; - - posted = ::PostMessage( dialog->GetSafeHwnd(), WM_USER_RESOLVE, 0, (LPARAM) serviceInstance ); - assert( posted ); - if( posted ) - { - serviceInstanceAutoPtr.release(); - } - break; - } - - default: - break; - } - } - catch( ... ) - { - // Don't let exceptions escape. - } -} - -//=========================================================================================================================== -// DNSNetworkAddressToString -// -// Note: Currently only supports IPv4 network addresses. -//=========================================================================================================================== - -static char * DNSNetworkAddressToString( const DNSNetworkAddress *inAddr, char *outString ) -{ - const DNSUInt8 * p; - DNSUInt16 port; - - p = inAddr->u.ipv4.addr.v8; - port = ntohs( inAddr->u.ipv4.port.v16 ); - if( port != kDNSPortInvalid ) - { - sprintf( outString, "%u.%u.%u.%u:%u", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ], port ); - } - else - { - sprintf( outString, "%u.%u.%u.%u", p[ 0 ], p[ 1 ], p[ 2 ], p[ 3 ] ); - } - return( outString ); -} - -//=========================================================================================================================== -// UTF8StringToStringObject -//=========================================================================================================================== - -static DWORD UTF8StringToStringObject( const char *inUTF8, CString &inObject ) -{ - DWORD err; - int n; - BSTR unicode; - - unicode = NULL; - - n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, NULL, 0 ); - if( n > 0 ) - { - unicode = (BSTR) malloc( (size_t)( n * sizeof( wchar_t ) ) ); - if( !unicode ) - { - err = ERROR_INSUFFICIENT_BUFFER; - goto exit; - } - - n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, unicode, n ); - try - { - inObject = unicode; - } - catch( ... ) - { - err = ERROR_NO_UNICODE_TRANSLATION; - goto exit; - } - } - else - { - inObject = ""; - } - err = 0; - -exit: - if( unicode ) - { - free( unicode ); - } - return( err ); -} diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/ChooserDialog.h b/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/ChooserDialog.h deleted file mode 100644 index 7acb0b5..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/ChooserDialog.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: ChooserDialog.h,v $ -Revision 1.1 2003/08/21 02:06:47 bradley -Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. - -Revision 1.4 2003/08/12 19:56:28 cheshire -Update to APSL 2.0 - -Revision 1.3 2003/07/02 21:20:06 cheshire - Update copyright notices, etc., in source code comments - -Revision 1.2 2002/09/21 20:44:55 zarzycki -Added APSL info - -Revision 1.1 2002/09/20 06:12:52 bradley -Rendezvous Browser for Windows - -*/ - -#if !defined(AFX_CHOOSERDIALOG_H__AC258704_B307_4901_9F98_A0AC022FD8AC__INCLUDED_) -#define AFX_CHOOSERDIALOG_H__AC258704_B307_4901_9F98_A0AC022FD8AC__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include -#include - -#include "afxcmn.h" - -#include "Resource.h" - -#include "DNSServices.h" - -//=========================================================================================================================== -// Structures -//=========================================================================================================================== - -struct ServiceInstanceInfo -{ - std::string name; - std::string type; - std::string domain; - std::string ip; - std::string text; - std::string ifIP; -}; - -struct ServiceTypeInfo -{ - std::string serviceType; - std::string description; - std::string urlScheme; -}; - -//=========================================================================================================================== -// ChooserDialog -//=========================================================================================================================== - -class ChooserDialog : public CDialog -{ - public: - - ChooserDialog(CWnd* pParent = NULL); - virtual ~ChooserDialog( void ); - - //{{AFX_DATA(ChooserDialog) - enum { IDD = IDD_CHOOSER_DIALOG }; - CListCtrl mServiceList; - CListCtrl mDomainList; - CListCtrl mChooserList; - //}}AFX_DATA - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(ChooserDialog) - public: - virtual BOOL PreTranslateMessage(MSG* pMsg); - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual void PostNcDestroy(); - //}}AFX_VIRTUAL - - protected: - - typedef std::vector < ServiceInstanceInfo > ServiceInstanceVector; - typedef std::vector < ServiceTypeInfo > ServiceTypeVector; - - HACCEL mMenuAcceleratorTable; - DNSBrowserRef mBrowser; - BOOL mIsServiceBrowsing; - ServiceInstanceVector mServiceInstances; - ServiceTypeVector mServiceTypes; - - public: - - void PopulateServicesList( void ); - void UpdateInfoDisplay( void ); - - void StartBrowsing( const char *inType, const char *inDomain ); - void StopBrowsing( void ); - - protected: - - //{{AFX_MSG(ChooserDialog) - virtual BOOL OnInitDialog(); - afx_msg void OnSysCommand(UINT nID, LPARAM lParam); - afx_msg void OnDomainListChanged(NMHDR* pNMHDR, LRESULT* pResult); - afx_msg void OnServiceListChanged(NMHDR* pNMHDR, LRESULT* pResult); - afx_msg void OnChooserListChanged(NMHDR* pNMHDR, LRESULT* pResult); - afx_msg void OnChooserListDoubleClick(NMHDR* pNMHDR, LRESULT* pResult); - afx_msg void OnAbout(); - afx_msg void OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu); - afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized); - afx_msg void OnFileClose(); - virtual void OnCancel(); - afx_msg void OnExit(); - afx_msg void OnClose(); - afx_msg void OnNcDestroy(); - //}}AFX_MSG - afx_msg LONG OnDomainAdd( WPARAM inWParam, LPARAM inLParam ); - afx_msg LONG OnDomainRemove( WPARAM inWParam, LPARAM inLParam ); - afx_msg LONG OnServiceAdd( WPARAM inWParam, LPARAM inLParam ); - afx_msg LONG OnServiceRemove( WPARAM inWParam, LPARAM inLParam ); - afx_msg LONG OnResolve( WPARAM inWParam, LPARAM inLParam ); - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_CHOOSERDIALOG_H__AC258704_B307_4901_9F98_A0AC022FD8AC__INCLUDED_) diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/StdAfx.cpp b/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/StdAfx.cpp deleted file mode 100644 index a26a1e7..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/StdAfx.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: StdAfx.cpp,v $ -Revision 1.1 2003/08/21 02:06:47 bradley -Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. - -Revision 1.4 2003/08/12 19:56:28 cheshire -Update to APSL 2.0 - -Revision 1.3 2003/07/02 21:20:06 cheshire - Update copyright notices, etc., in source code comments - -Revision 1.2 2002/09/21 20:44:55 zarzycki -Added APSL info - -Revision 1.1 2002/09/20 06:12:53 bradley -Rendezvous Browser for Windows - -*/ - -#include "stdafx.h" diff --git a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/StdAfx.h b/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/StdAfx.h deleted file mode 100644 index 3c16ff7..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/Windows/Sources/StdAfx.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: StdAfx.h,v $ -Revision 1.1 2003/08/21 02:06:47 bradley -Moved Rendezvous Browser for non-Windows CE into Windows sub-folder. - -Revision 1.4 2003/08/12 19:56:28 cheshire -Update to APSL 2.0 - -Revision 1.3 2003/07/02 21:20:06 cheshire - Update copyright notices, etc., in source code comments - -Revision 1.2 2002/09/21 20:44:56 zarzycki -Added APSL info - -Revision 1.1 2002/09/20 06:12:53 bradley -Rendezvous Browser for Windows - -*/ - -#if !defined(AFX_STDAFX_H__424305D2_0A97_4AA0_B9B1_A7D90D18EBA0__INCLUDED_) -#define AFX_STDAFX_H__424305D2_0A97_4AA0_B9B1_A7D90D18EBA0__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers - -#include // MFC core and standard components -#include // MFC extensions -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - -#include // MFC socket extensions - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#include - -#include "DNSServices.h" - -#include "Application.h" - -#include "ChooserDialog.h" - -#endif // !defined(AFX_STDAFX_H__424305D2_0A97_4AA0_B9B1_A7D90D18EBA0__INCLUDED_) diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Application.vcc b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Application.vcc deleted file mode 100644 index 22f443d..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Application.vcc +++ /dev/null @@ -1,37 +0,0 @@ -; CLW file contains information for the MFC ClassWizard - -[General Info] -Version=1 -LastClass=BrowserDialog -LastTemplate=CDialog -NewFileInclude1=#include "stdafx.h" -NewFileInclude2=#include "Application.h" - -ClassCount=3 -Class1=Application -Class2=BrowserDialog - -ResourceCount=3 -Resource2=IDR_MAINFRAME -Resource3=IDD_APPLICATION_DIALOG - -[CLS:Application] -Type=0 -HeaderFile=Application.h -ImplementationFile=Application.cpp -Filter=N - -[CLS:BrowserDialog] -Type=0 -HeaderFile=BrowserDialog.h -ImplementationFile=BrowserDialog.cpp -Filter=D - - -[DLG:IDD_APPLICATION_DIALOG] -Type=1 -ControlCount=3 -Control1=IDOK,button,1342242817 -Control2=IDCANCEL,button,1342242816 -Control3=IDC_STATIC,static,1342308352 -Class=BrowserDialog diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Application.vcp b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Application.vcp deleted file mode 100644 index 7f62479..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Application.vcp +++ /dev/null @@ -1,499 +0,0 @@ -# Microsoft eMbedded Visual Tools Project File - Name="Application" - Package Owner=<4> -# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (WCE ARMV4) Application" 0xa301 -# TARGTYPE "Win32 (WCE emulator) Application" 0xa601 - -CFG=Application - Win32 (WCE emulator) Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "Application.vcn". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "Application.vcn" CFG="Application - Win32 (WCE emulator) Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "Application - Win32 (WCE emulator) Release" (based on "Win32 (WCE emulator) Application") -!MESSAGE "Application - Win32 (WCE emulator) Debug" (based on "Win32 (WCE emulator) Application") -!MESSAGE "Application - Win32 (WCE ARMV4) Release" (based on "Win32 (WCE ARMV4) Application") -!MESSAGE "Application - Win32 (WCE ARMV4) Debug" (based on "Win32 (WCE ARMV4) Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -# PROP ATL_Project 2 - -!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" - -# PROP BASE Use_MFC 2 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "emulatorRel" -# PROP BASE Intermediate_Dir "emulatorRel" -# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" -# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" -# PROP BASE Target_Dir "" -# PROP Use_MFC 2 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "emulatorRel" -# PROP Intermediate_Dir "emulatorRel" -# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" -# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -RSC=rc.exe -# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /d "_AFXDLL" /r -# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /d "_AFXDLL" /r -CPP=cl.exe -# ADD BASE CPP /nologo /W3 /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /D "_WIN32_WCE_CEPC" /D "_AFXDLL" /Yu"stdafx.h" /Gs8192 /GF /O2 /c -# ADD CPP /nologo /W3 /I "Resources" /I "Sources" /I "..\..\..\DNSServices" /I "..\..\..\..\mDNSCore" /I "..\..\..\..\mDNSCore\PlatformSupport" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /D "_WIN32_WCE_CEPC" /D "_AFXDLL" /Gs8192 /GF /O2 /c -# SUBTRACT CPP /YX /Yc /Yu -MTL=midl.exe -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /subsystem:$(CESubsystem) /MACHINE:IX86 -# ADD LINK32 ws2.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /subsystem:$(CESubsystem) /MACHINE:IX86 - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" - -# PROP BASE Use_MFC 2 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "emulatorDbg" -# PROP BASE Intermediate_Dir "emulatorDbg" -# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" -# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" -# PROP BASE Target_Dir "" -# PROP Use_MFC 2 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "emulatorDbg" -# PROP Intermediate_Dir "emulatorDbg" -# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}" -# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -RSC=rc.exe -# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /d "_AFXDLL" /r -# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /d "_AFXDLL" /r -CPP=cl.exe -# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "_WIN32_WCE_CEPC" /D "_AFXDLL" /Yu"stdafx.h" /Gs8192 /GF /c -# ADD CPP /nologo /W3 /WX /Zi /Od /I "Resources" /I "Sources" /I "..\..\..\DNSServices" /I "..\..\..\..\mDNSCore" /I "..\..\..\..\mDNSCore\PlatformSupport" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "_WIN32_WCE_CEPC" /D "_AFXDLL" /FR /Gs8192 /GF /c -MTL=midl.exe -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /debug /subsystem:$(CESubsystem) /MACHINE:IX86 -# ADD LINK32 ws2.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /debug /subsystem:$(CESubsystem) /MACHINE:IX86 - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" - -# PROP BASE Use_MFC 2 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "ARMV4Rel" -# PROP BASE Intermediate_Dir "ARMV4Rel" -# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" -# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" -# PROP BASE Target_Dir "" -# PROP Use_MFC 2 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "ARMV4Rel" -# PROP Intermediate_Dir "ARMV4Rel" -# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" -# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -RSC=rc.exe -# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /d "_AFXDLL" /r -# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /d "_AFXDLL" /r -CPP=clarm.exe -# ADD BASE CPP /nologo /W3 /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /D "_AFXDLL" /Yu"stdafx.h" /O2 /M$(CECrtMT) /c -# ADD CPP /nologo /W3 /I "Resources" /I "Sources" /I "..\..\..\DNSServices" /I "..\..\..\..\mDNSCore" /I "..\..\..\..\mDNSCore\PlatformSupport" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /D "_AFXDLL" /O2 /M$(CECrtMT) /c -# SUBTRACT CPP /YX /Yc /Yu -MTL=midl.exe -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM -# ADD LINK32 ws2.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" - -# PROP BASE Use_MFC 2 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "ARMV4Dbg" -# PROP BASE Intermediate_Dir "ARMV4Dbg" -# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" -# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" -# PROP BASE Target_Dir "" -# PROP Use_MFC 2 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "ARMV4Dbg" -# PROP Intermediate_Dir "ARMV4Dbg" -# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}" -# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -RSC=rc.exe -# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /d "_AFXDLL" /r -# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /d "_AFXDLL" /r -CPP=clarm.exe -# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_AFXDLL" /Yu"stdafx.h" /M$(CECrtMTDebug) /c -# ADD CPP /nologo /W3 /Zi /Od /I "Resources" /I "Sources" /I "..\..\..\DNSServices" /I "..\..\..\..\mDNSCore" /I "..\..\..\..\mDNSCore\PlatformSupport" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /D "_AFXDLL" /M$(CECrtMTDebug) /c -# SUBTRACT CPP /YX /Yc /Yu -MTL=midl.exe -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /debug /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM -# ADD LINK32 ws2.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"wWinMainCRTStartup" /debug /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM - -!ENDIF - -# Begin Target - -# Name "Application - Win32 (WCE emulator) Release" -# Name "Application - Win32 (WCE emulator) Debug" -# Name "Application - Win32 (WCE ARMV4) Release" -# Name "Application - Win32 (WCE ARMV4) Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\Sources\Application.cpp - -!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" - -DEP_CPP_APPLI=\ - "..\..\..\DNSServices\DNSServices.h"\ - ".\Sources\Application.h"\ - ".\Sources\BrowserDialog.h"\ - ".\Sources\StdAfx.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" - -DEP_CPP_APPLI=\ - "..\..\..\DNSServices\DNSServices.h"\ - ".\Sources\Application.h"\ - ".\Sources\BrowserDialog.h"\ - ".\Sources\StdAfx.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" - -DEP_CPP_APPLI=\ - "..\..\..\DNSServices\DNSServices.h"\ - ".\Sources\Application.h"\ - ".\Sources\BrowserDialog.h"\ - ".\Sources\StdAfx.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" - -DEP_CPP_APPLI=\ - "..\..\..\DNSServices\DNSServices.h"\ - ".\Sources\Application.h"\ - ".\Sources\BrowserDialog.h"\ - ".\Sources\StdAfx.h"\ - - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\Sources\Application.h -# End Source File -# Begin Source File - -SOURCE=.\Sources\BrowserDialog.cpp - -!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" - -DEP_CPP_BROWS=\ - ".\Sources\Application.h"\ - ".\Sources\BrowserDialog.h"\ - ".\Sources\StdAfx.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" - -DEP_CPP_BROWS=\ - "..\..\..\DNSServices\DNSServices.h"\ - ".\Sources\Application.h"\ - ".\Sources\BrowserDialog.h"\ - ".\Sources\StdAfx.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" - -DEP_CPP_BROWS=\ - ".\Sources\Application.h"\ - ".\Sources\BrowserDialog.h"\ - ".\Sources\StdAfx.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" - -DEP_CPP_BROWS=\ - ".\Sources\Application.h"\ - ".\Sources\BrowserDialog.h"\ - ".\Sources\StdAfx.h"\ - - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\Sources\BrowserDialog.h -# End Source File -# Begin Source File - -SOURCE=.\Sources\StdAfx.cpp - -!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" - -DEP_CPP_STDAF=\ - ".\Sources\StdAfx.h"\ - -# ADD CPP /Yc"stdafx.h" - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" - -DEP_CPP_STDAF=\ - ".\Sources\StdAfx.h"\ - -# ADD CPP /Yc"stdafx.h" - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" - -DEP_CPP_STDAF=\ - ".\Sources\StdAfx.h"\ - -# ADD CPP /Yc"stdafx.h" - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" - -DEP_CPP_STDAF=\ - ".\Sources\StdAfx.h"\ - -# ADD CPP /Yc"stdafx.h" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\Sources\StdAfx.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\Resources\Application.ico -# End Source File -# Begin Source File - -SOURCE=.\Resources\Application.rc - -!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=.\Resources\Application.rc2 -# PROP Exclude_From_Scan -1 -# PROP BASE Exclude_From_Build 1 -# PROP Exclude_From_Build 1 -# End Source File -# Begin Source File - -SOURCE=.\Resources\newres.h -# End Source File -# Begin Source File - -SOURCE=.\Resources\Resource.h -# End Source File -# End Group -# Begin Group "Rendezvous" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=..\..\..\DNSServices\DNSServices.c - -!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" - -DEP_CPP_DNSSE=\ - "..\..\..\DNSServices\DNSServices.h"\ - "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ - "..\..\..\..\mDNSCore\mDNSDebug.h"\ - "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" - -DEP_CPP_DNSSE=\ - "..\..\..\DNSServices\DNSServices.h"\ - "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ - "..\..\..\..\mDNSCore\mDNSDebug.h"\ - "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" - -DEP_CPP_DNSSE=\ - "..\..\..\DNSServices\DNSServices.h"\ - "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ - "..\..\..\..\mDNSCore\mDNSDebug.h"\ - "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" - -DEP_CPP_DNSSE=\ - "..\..\..\DNSServices\DNSServices.h"\ - "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ - "..\..\..\..\mDNSCore\mDNSDebug.h"\ - "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ - - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=..\..\..\DNSServices\DNSServices.h -# End Source File -# Begin Source File - -SOURCE=..\..\..\..\mDNSCore\mDNS.c - -!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" - -DEP_CPP_MDNS_=\ - "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ - "..\..\..\..\mDNSCore\mDNSDebug.h"\ - "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" - -DEP_CPP_MDNS_=\ - "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ - "..\..\..\..\mDNSCore\mDNSDebug.h"\ - "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" - -DEP_CPP_MDNS_=\ - "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ - "..\..\..\..\mDNSCore\mDNSDebug.h"\ - "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" - -DEP_CPP_MDNS_=\ - "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ - "..\..\..\..\mDNSCore\mDNSDebug.h"\ - "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ - - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=..\..\..\..\mDNSCore\mDNSClientAPI.h -# End Source File -# Begin Source File - -SOURCE=..\..\..\..\mDNSCore\mDNSDebug.h -# End Source File -# Begin Source File - -SOURCE=..\..\..\..\mDNSCore\mDNSPlatformFunctions.h -# End Source File -# Begin Source File - -SOURCE=..\..\..\mDNSWin32.c - -!IF "$(CFG)" == "Application - Win32 (WCE emulator) Release" - -DEP_CPP_MDNSW=\ - "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ - "..\..\..\..\mDNSCore\mDNSDebug.h"\ - "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ - "..\..\..\mDNSWin32.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE emulator) Debug" - -DEP_CPP_MDNSW=\ - "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ - "..\..\..\..\mDNSCore\mDNSDebug.h"\ - "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ - "..\..\..\mDNSWin32.h"\ - -# ADD CPP /W3 - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Release" - -DEP_CPP_MDNSW=\ - "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ - "..\..\..\..\mDNSCore\mDNSDebug.h"\ - "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ - "..\..\..\mDNSWin32.h"\ - - -!ELSEIF "$(CFG)" == "Application - Win32 (WCE ARMV4) Debug" - -DEP_CPP_MDNSW=\ - "..\..\..\..\mDNSCore\mDNSClientAPI.h"\ - "..\..\..\..\mDNSCore\mDNSDebug.h"\ - "..\..\..\..\mDNSCore\mDNSPlatformFunctions.h"\ - "..\..\..\mDNSWin32.h"\ - - -!ENDIF - -# End Source File -# Begin Source File - -SOURCE=..\..\..\mDNSWin32.h -# End Source File -# End Group -# End Target -# End Project diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Application.vcw b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Application.vcw deleted file mode 100644 index 11ef513..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Application.vcw +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "Application"=.\Application.vcp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/Application.ico b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/Application.ico deleted file mode 100644 index 51a182e..0000000 Binary files a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/Application.ico and /dev/null differ diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/Application.rc b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/Application.rc deleted file mode 100644 index c453f27..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/Application.rc +++ /dev/null @@ -1,194 +0,0 @@ -//Microsoft eMbedded Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" -#include "newres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""afxres.h""\r\n" - "#include ""newres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "#define _AFX_NO_SPLITTER_RESOURCES\r\n" - "#define _AFX_NO_OLE_RESOURCES\r\n" - "#define _AFX_NO_TRACKER_RESOURCES\r\n" - "#define _AFX_NO_PROPERTY_RESOURCES\r\n" - "\r\n" - "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" - "#ifdef _WIN32\r\n" - "LANGUAGE 9, 1\r\n" - "#pragma code_page(1252)\r\n" - "#endif //_WIN32\r\n" - "#include ""Resources\\Application.rc2"" // non-Microsoft eMbedded Visual C++ edited resources\r\n" - "#include ""afxres.rc"" // Standard components\r\n" - "#include ""wceres.rc"" // WCE-specific components\r\n" - "#endif\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDR_MAINFRAME ICON DISCARDABLE "Application.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_APPLICATION_DIALOG DIALOG DISCARDABLE 0, 0, 139, 153 -STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION -EXSTYLE WS_EX_APPWINDOW | 0x80000000L -CAPTION "Rendezvous Browser" -FONT 8, "System" -BEGIN - CONTROL "List1",IDC_BROWSE_LIST,"SysListView32",LVS_REPORT | - LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER | - WS_BORDER | WS_TABSTOP,7,7,125,141 -END - - -#ifndef _MAC -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,1 - PRODUCTVERSION 1,0,0,1 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "\0" - VALUE "CompanyName", "Apple Computer, Inc.\0" - VALUE "FileDescription", "Rendezvous Browser for Windows CE\0" - VALUE "FileVersion", "1, 0, 0, 1\0" - VALUE "InternalName", "Application\0" - VALUE "LegalCopyright", "Copyright © 2003 Apple Computer, Inc.\0" - VALUE "LegalTrademarks", "\0" - VALUE "OriginalFilename", "Application.exe\0" - VALUE "PrivateBuild", "\0" - VALUE "ProductName", "Rendezvous Browser for Windows CE\0" - VALUE "ProductVersion", "1, 0, 0, 1\0" - VALUE "SpecialBuild", "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // !_MAC - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE -BEGIN - IDD_APPLICATION_DIALOG, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 132 - TOPMARGIN, 7 - BOTTOMMARGIN, 146 - END -END -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE DISCARDABLE -BEGIN - IDP_SOCKETS_INIT_FAILED "Windows CE sockets initialization failed." - IDS_BROWSER_LIST_COLUMN_NAME "Name" -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// -#define _AFX_NO_SPLITTER_RESOURCES -#define _AFX_NO_OLE_RESOURCES -#define _AFX_NO_TRACKER_RESOURCES -#define _AFX_NO_PROPERTY_RESOURCES - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE 9, 1 -#pragma code_page(1252) -#endif //_WIN32 -#include "Resources\Application.rc2" // non-Microsoft eMbedded Visual C++ edited resources -#include "afxres.rc" // Standard components -#include "wceres.rc" // WCE-specific components -#endif - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/Application.rc2 b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/Application.rc2 deleted file mode 100644 index 29c9fe7..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/Application.rc2 +++ /dev/null @@ -1,13 +0,0 @@ -// -// APPLICATION.RC2 - resources Microsoft eMbedded Visual C++ does not edit directly -// - -#ifdef APSTUDIO_INVOKED - #error this file is not editable by Microsoft eMbedded Visual C++ -#endif //APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// Add manually edited resources here... - -///////////////////////////////////////////////////////////////////////////// diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/newres.h b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/newres.h deleted file mode 100644 index 31c3a43..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/newres.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __NEWRES_H__ -#define __NEWRES_H__ - -#define SHMENUBAR RCDATA -#if !(defined(_WIN32_WCE_PSPC) && (_WIN32_WCE >= 300)) - #undef HDS_HORZ - #undef HDS_BUTTONS - #undef HDS_HIDDEN - - #include - // for MenuBar - #define I_IMAGENONE (-2) - #define NOMENU 0xFFFF - #define IDS_SHNEW 1 - #define IDM_SHAREDNEW 10 - #define IDM_SHAREDNEWDEFAULT 11 - - // for Tab Control - #define TCS_SCROLLOPPOSITE 0x0001 // assumes multiline tab - #define TCS_BOTTOM 0x0002 - #define TCS_RIGHT 0x0002 - #define TCS_VERTICAL 0x0080 - #define TCS_MULTISELECT 0x0004 // allow multi-select in button mode - #define TCS_FLATBUTTONS 0x0008 -#endif //_WIN32_WCE_PSPC - - -#endif //__NEWRES_H__ diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/resource.h b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/resource.h deleted file mode 100644 index 0337c56..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Resources/resource.h +++ /dev/null @@ -1,22 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft eMbedded Visual C++ generated include file. -// Used by Application.rc -// -#define IDD_APPLICATION_DIALOG 102 -#define IDP_SOCKETS_INIT_FAILED 103 -#define IDS_BROWSER_LIST_COLUMN_NAME 104 -#define IDR_MAINFRAME 128 -#define IDC_BROWSE_LIST 1000 -#define IDC_IP_TEXT 1003 -#define IDC_TXT_TEXT 1004 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 129 -#define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1005 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/Application.cpp b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/Application.cpp deleted file mode 100644 index ba28f41..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/Application.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: Application.cpp,v $ -Revision 1.1 2003/08/21 02:16:10 bradley -Rendezvous Browser for HTTP services for Windows CE/PocketPC. - -*/ - -#include "stdafx.h" - -#include "DNSServices.h" - -#include "BrowserDialog.h" - -#include "Application.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -//=========================================================================================================================== -// Message Map -//=========================================================================================================================== - -BEGIN_MESSAGE_MAP(Application, CWinApp) - //{{AFX_MSG_MAP(Application) - // NOTE - the ClassWizard will add and remove mapping macros here. - // DO NOT EDIT what you see in these blocks of generated code! - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -//=========================================================================================================================== -// Globals -//=========================================================================================================================== - -Application gApp; - -//=========================================================================================================================== -// Application -//=========================================================================================================================== - -Application::Application() - : CWinApp() -{ - // -} - -//=========================================================================================================================== -// InitInstance -//=========================================================================================================================== - -BOOL Application::InitInstance() -{ - DNSStatus err; - BrowserDialog dialog; - BOOL dnsInitialized; - - dnsInitialized = FALSE; - - if( !AfxSocketInit() ) - { - AfxMessageBox( IDP_SOCKETS_INIT_FAILED ); - goto exit; - } - - err = DNSServicesInitialize( kDNSFlagAdvertise, 0 ); - if( err ) - { - AfxMessageBox( IDP_SOCKETS_INIT_FAILED ); - goto exit; - } - dnsInitialized = TRUE; - - // Display the main browser dialog. - - m_pMainWnd = &dialog; - dialog.DoModal(); - - // Dialog has been closed. Return false to exit the app and not start the app's message pump. - -exit: - if( dnsInitialized ) - { - DNSServicesFinalize(); - } - return( FALSE ); -} diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/Application.h b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/Application.h deleted file mode 100644 index 1f4fe13..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/Application.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: Application.h,v $ -Revision 1.1 2003/08/21 02:16:10 bradley -Rendezvous Browser for HTTP services for Windows CE/PocketPC. - -*/ - -#if !defined(AFX_APPLICATION_H__E2E51302_D643_458E_A7A5_5157233D1E5C__INCLUDED_) -#define AFX_APPLICATION_H__E2E51302_D643_458E_A7A5_5157233D1E5C__INCLUDED_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#ifndef __AFXWIN_H__ - #error include 'stdafx.h' before including this file for PCH -#endif - -#include "Resource.h" - -//=========================================================================================================================== -// Application -//=========================================================================================================================== - -class Application : public CWinApp -{ - public: - - Application(); - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(Application) - public: - virtual BOOL InitInstance(); - //}}AFX_VIRTUAL - - //{{AFX_MSG(Application) - // NOTE - the ClassWizard will add and remove member functions here. - // DO NOT EDIT what you see in these blocks of generated code ! - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_APPLICATION_H__E2E51302_D643_458E_A7A5_5157233D1E5C__INCLUDED_) diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/BrowserDialog.cpp b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/BrowserDialog.cpp deleted file mode 100644 index 991fc08..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/BrowserDialog.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: BrowserDialog.cpp,v $ -Revision 1.1 2003/08/21 02:16:10 bradley -Rendezvous Browser for HTTP services for Windows CE/PocketPC. - -*/ - -#include "stdafx.h" - -#include "Application.h" - -#include "DNSServices.h" - -#include "BrowserDialog.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -//=========================================================================================================================== -// Message Map -//=========================================================================================================================== - -BEGIN_MESSAGE_MAP(BrowserDialog, CDialog) - //{{AFX_MSG_MAP(BrowserDialog) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -static DWORD UTF8StringToStringObject( const char *inUTF8, CString &inObject ); - -//=========================================================================================================================== -// BrowserDialog -//=========================================================================================================================== - -BrowserDialog::BrowserDialog( CWnd *inParent ) - : CDialog( BrowserDialog::IDD, inParent ) -{ - //{{AFX_DATA_INIT(BrowserDialog) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT - - // Note that LoadIcon does not require a subsequent DestroyIcon in Win32. - - mIcon = AfxGetApp()->LoadIcon( IDR_MAINFRAME ); -} - -//=========================================================================================================================== -// DoDataExchange -//=========================================================================================================================== - -void BrowserDialog::DoDataExchange( CDataExchange *pDX ) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(BrowserDialog) - DDX_Control(pDX, IDC_BROWSE_LIST, mBrowserList); - //}}AFX_DATA_MAP -} - -//=========================================================================================================================== -// OnInitDialog -//=========================================================================================================================== - -BOOL BrowserDialog::OnInitDialog() -{ - CString s; - - CDialog::OnInitDialog(); - - // Set the icon for this dialog. The framework does this automatically when the application's main window is not a dialog. - - SetIcon( mIcon, TRUE ); // Set big icon - SetIcon( mIcon, FALSE ); // Set small icon - - CenterWindow( GetDesktopWindow() ); - - // Set up the list. - - CRect rect; - - s.LoadString( IDS_BROWSER_LIST_COLUMN_NAME ); - mBrowserList.GetWindowRect( rect ); - mBrowserList.InsertColumn( 0, s, LVCFMT_LEFT, rect.Width() - 8 ); - - // Start browsing for services. - - DNSStatus err; - - err = DNSBrowserCreate( 0, BrowserCallBack, this, &mBrowser ); - if( err ) - { - AfxMessageBox( IDP_SOCKETS_INIT_FAILED ); - goto exit; - } - - err = DNSBrowserStartServiceSearch( mBrowser, 0, "_http._tcp", NULL ); - if( err ) - { - AfxMessageBox( IDP_SOCKETS_INIT_FAILED ); - goto exit; - } - -exit: - return( TRUE ); -} - -//=========================================================================================================================== -// BrowserCallBack [static] -//=========================================================================================================================== - -void - BrowserDialog::BrowserCallBack( - void * inContext, - DNSBrowserRef inRef, - DNSStatus inStatusCode, - const DNSBrowserEvent * inEvent ) -{ - BrowserDialog * dialog; - - DNS_UNUSED( inStatusCode ); - dialog = reinterpret_cast < BrowserDialog * > ( inContext ); - - switch( inEvent->type ) - { - case kDNSBrowserEventTypeAddService: - dialog->BrowserAddService( inEvent->data.addService.name ); - break; - - case kDNSBrowserEventTypeRemoveService: - dialog->BrowserRemoveService( inEvent->data.removeService.name ); - break; - - default: - break; - } -} - -//=========================================================================================================================== -// BrowserAddService -//=========================================================================================================================== - -void BrowserDialog::BrowserAddService( const char *inName ) -{ - BrowserEntry newEntry; - INT_PTR n; - INT_PTR i; - - UTF8StringToStringObject( inName, newEntry.name ); - - n = mBrowserEntries.GetSize(); - for( i = 0; i < n; ++i ) - { - BrowserEntry & entry = mBrowserEntries.ElementAt( i ); - - if( entry.name.CompareNoCase( newEntry.name ) == 0 ) - { - break; - } - } - if( i >= n ) - { - mBrowserEntries.Add( newEntry ); - mBrowserList.InsertItem( i, newEntry.name ); - } -} - -//=========================================================================================================================== -// BrowserRemoveService -//=========================================================================================================================== - -void BrowserDialog::BrowserRemoveService( const char *inName ) -{ - BrowserEntry newEntry; - INT_PTR n; - INT_PTR i; - - UTF8StringToStringObject( inName, newEntry.name ); - - n = mBrowserEntries.GetSize(); - for( i = 0; i < n; ++i ) - { - BrowserEntry & entry = mBrowserEntries.ElementAt( i ); - - if( entry.name.CompareNoCase( newEntry.name ) == 0 ) - { - break; - } - } - if( i < n ) - { - mBrowserEntries.RemoveAt( i ); - mBrowserList.DeleteItem( i ); - } -} - -#if 0 -#pragma mark - -#endif - -//=========================================================================================================================== -// UTF8StringToStringObject -//=========================================================================================================================== - -static DWORD UTF8StringToStringObject( const char *inUTF8, CString &inObject ) -{ - DWORD err; - int n; - wchar_t * unicode; - - unicode = NULL; - - n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, NULL, 0 ); - if( n > 0 ) - { - unicode = (wchar_t *) malloc( (size_t)( n * sizeof( wchar_t ) ) ); - if( !unicode ) { err = ERROR_INSUFFICIENT_BUFFER; goto exit; }; - - n = MultiByteToWideChar( CP_UTF8, 0, inUTF8, -1, unicode, n ); - inObject = unicode; - } - else - { - inObject = ""; - } - err = 0; - -exit: - if( unicode ) - { - free( unicode ); - } - return( err ); -} diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/BrowserDialog.h b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/BrowserDialog.h deleted file mode 100644 index 7777510..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/BrowserDialog.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: BrowserDialog.h,v $ -Revision 1.1 2003/08/21 02:16:10 bradley -Rendezvous Browser for HTTP services for Windows CE/PocketPC. - -*/ - -#if !defined(AFX_BROWSERDIALOG_H__DECC5C82_C1C6_4630_B8D5_E1DDE570A061__INCLUDED_) -#define AFX_BROWSERDIALOG_H__DECC5C82_C1C6_4630_B8D5_E1DDE570A061__INCLUDED_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - -#include "afxtempl.h" -#include "Resource.h" - -#include "DNSServices.h" - -//=========================================================================================================================== -// BrowserDialog -//=========================================================================================================================== - -class BrowserDialog : public CDialog -{ - public: - - BrowserDialog( CWnd *inParent = NULL ); - - //{{AFX_DATA(BrowserDialog) - enum { IDD = IDD_APPLICATION_DIALOG }; - CListCtrl mBrowserList; - //}}AFX_DATA - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(BrowserDialog) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - static void - BrowserCallBack( - void * inContext, - DNSBrowserRef inRef, - DNSStatus inStatusCode, - const DNSBrowserEvent * inEvent ); - - void BrowserAddService( const char *inName ); - void BrowserRemoveService( const char *inName ); - - protected: - - struct BrowserEntry - { - CString name; - }; - - - HICON mIcon; - DNSBrowserRef mBrowser; - CArray < BrowserEntry, BrowserEntry > mBrowserEntries; - - // Generated message map functions - //{{AFX_MSG(BrowserDialog) - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_BROWSERDIALOG_H__DECC5C82_C1C6_4630_B8D5_E1DDE570A061__INCLUDED_) diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/StdAfx.cpp b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/StdAfx.cpp deleted file mode 100644 index 6622a5d..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/StdAfx.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: StdAfx.cpp,v $ -Revision 1.1 2003/08/21 02:16:10 bradley -Rendezvous Browser for HTTP services for Windows CE/PocketPC. - -*/ - -#include "stdafx.h" diff --git a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/StdAfx.h b/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/StdAfx.h deleted file mode 100644 index 3672152..0000000 --- a/mDNSWindows/Applications/RendezvousBrowser/WindowsCE/Sources/StdAfx.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: StdAfx.h,v $ -Revision 1.1 2003/08/21 02:16:10 bradley -Rendezvous Browser for HTTP services for Windows CE/PocketPC. - -*/ - -#if !defined(AFX_STDAFX_H__7F91E52B_CF39_429D_837D_599CE0B2B3D6__INCLUDED_) -#define AFX_STDAFX_H__7F91E52B_CF39_429D_837D_599CE0B2B3D6__INCLUDED_ - -#if _MSC_VER >= 1000 -#pragma once -#endif // _MSC_VER >= 1000 - - - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers - -#include // MFC core and standard components -#include // MFC extensions - -#if defined(_AFXDLL) -#include // MFC support for Internet Explorer 4 Common Controls -#endif - -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - -#include // MFC socket extensions - -//{{AFX_INSERT_LOCATION}} -// Microsoft eMbedded Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__7F91E52B_CF39_429D_837D_599CE0B2B3D6__INCLUDED_) diff --git a/mDNSWindows/Applications/RendezvousTest/Tool.c b/mDNSWindows/Applications/RendezvousTest/Tool.c deleted file mode 100644 index 7e49566..0000000 --- a/mDNSWindows/Applications/RendezvousTest/Tool.c +++ /dev/null @@ -1,1047 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: Tool.c,v $ -Revision 1.7 2003/08/20 07:06:34 bradley -Update to APSL 2.0. Updated change history to match other mDNSResponder files. - -Revision 1.6 2003/08/20 06:50:55 bradley -Updated to latest internal version of the Rendezvous for Windows code: Re-did everything to support -the latest DNSServices APIs (proxies, record updates, etc.); Added support for testing the platform -neutral DNSServices-based emulation layer for the Mac OS X DNSServiceDiscovery API. - -*/ - -#if( defined( _MSC_VER ) ) - #pragma warning( disable:4068 ) // Disable "unknown pragma" warning for "pragma unused". - #pragma warning( disable:4127 ) // Disable "conditional expression is constant" warning for debug macros. - #pragma warning( disable:4311 ) // Disable "type cast : pointer truncation from void *const to int". - - // No stdint.h with Visual C++ so emulate it here. - - typedef signed char int8_t; // C99 stdint.h not supported in VC++/VS.NET yet. - typedef unsigned char uint8_t; // C99 stdint.h not supported in VC++/VS.NET yet. - typedef signed short int16_t; // C99 stdint.h not supported in VC++/VS.NET yet. - typedef unsigned short uint16_t; // C99 stdint.h not supported in VC++/VS.NET yet. - typedef signed long int32_t; // C99 stdint.h not supported in VC++/VS.NET yet. - typedef unsigned long uint32_t; // C99 stdint.h not supported in VC++/VS.NET yet. -#else - #include -#endif - -#include -#include - -#if( __MACH__ ) - #include - #include - #include - - #include - #include - - #include -#else - #define WIN32_LEAN_AND_MEAN - - #include - #include -#endif - -#include "DNSServices.h" -#include "DNSServiceDiscovery.h" - -//=========================================================================================================================== -// Macros -//=========================================================================================================================== - -#if( !TARGET_OS_MAC ) - #define require_action_string( X, LABEL, ACTION, STR ) \ - do \ - { \ - if( !( X ) ) \ - { \ - fprintf( stderr, "%s\n", ( STR ) ); \ - { ACTION; } \ - goto LABEL; \ - } \ - } while( 0 ) - - #define require_string( X, LABEL, STR ) \ - do \ - { \ - if( !( X ) ) \ - { \ - fprintf( stderr, "%s\n", ( STR ) ); \ - goto LABEL; \ - \ - } \ - } while( 0 ) - - #define require_noerr_string( ERR, LABEL, STR ) \ - do \ - { \ - if( ( ERR ) != 0 ) \ - { \ - fprintf( stderr, "%s (%ld)\n", ( STR ), ( ERR ) ); \ - goto LABEL; \ - } \ - } while( 0 ) -#endif - -//=========================================================================================================================== -// Prototypes -//=========================================================================================================================== - -int main( int argc, char* argv[] ); -static void Usage( void ); -static int ProcessArgs( int argc, char* argv[] ); -static DNSStatus ProcessPreset( int inPreset ); - -#if( __MACH__ ) - static void SigIntHandler( int inSignalNumber ); -#endif - -#if( defined( WINVER ) ) - static BOOL WINAPI ConsoleControlHandler( DWORD inControlEvent ); -#endif - -static void BrowserCallBack( void *inContext, DNSBrowserRef inRef, DNSStatus inStatusCode, const DNSBrowserEvent *inEvent ); -static void ResolverCallBack( void *inContext, DNSResolverRef inRef, DNSStatus inStatusCode, const DNSResolverEvent *inEvent ); - -static void - RegistrationCallBack( - void * inContext, - DNSRegistrationRef inRef, - DNSStatus inStatusCode, - const DNSRegistrationEvent * inEvent ); - -static void - HostRegistrationCallBack( - void * inContext, - DNSHostRegistrationRef inRef, - DNSStatus inStatusCode, - void * inData ); - -static void - EmulatedBrowserCallBack( - DNSServiceBrowserReplyResultType inResult, - const char * inName, - const char * inType, - const char * inDomain, - DNSServiceDiscoveryReplyFlags inFlags, - void * inContext ); - -static void - EmulatedDomainEnumerationCallBack( - DNSServiceDomainEnumerationReplyResultType inResult, - const char * inDomain, - DNSServiceDiscoveryReplyFlags inFlags, - void * inContext ); - -static void - EmulatedResolverCallBack( - struct sockaddr * inInterfaceAddr, - struct sockaddr * inAddr, - const char * inTextRecord, - DNSServiceDiscoveryReplyFlags inFlags, - void * inContext ); - -static void EmulatedRegistrationCallBack( DNSServiceRegistrationReplyErrorType inResult, void *inContext ); - -static char * IPv4ToString( DNSOpaque32 inIP, char *outString ); - -//=========================================================================================================================== -// Globals -//=========================================================================================================================== - -#if( defined( WINVER ) ) - static volatile int gQuit = 0; -#endif - -static int gPrintTXTRecords = 1; - -// Presets - -typedef struct PresetData PresetData; -struct PresetData -{ - int argc; - char * argv[ 16 ]; -}; - -#if 0 -#pragma mark == Presets == -#endif - -static const PresetData gPresets[] = -{ - /* 01 */ { 2, { "rendezvous", "-bbd" } }, - /* 02 */ { 4, { "rendezvous", "-bs", "_airport._tcp", "local." } }, - /* 03 */ { 4, { "rendezvous", "-bs", "_xserveraid._tcp", "local." } }, - /* 04 */ { 3, { "rendezvous", "-rdb", "apple.com" } }, - /* 05 */ { 7, { "rendezvous", "-rs", "My Fake AirPort", "_airport._tcp", "local.", "1234", "My Fake Info" } }, - /* 06 */ { 7, { "rendezvous", "-rs", "My Fake Xserve RAID", "_xserveraid._tcp", "local.", "1234", "My Fake Info" } }, - /* 07 */ { 7, { "rendezvous", "-rs", "My Fake Web Server", "_http._tcp", "local.", "8080", "index.html" } }, - /* 08 */ { 9, { "rendezvous", "-rps", "www.apple.com", "17.254.0.91", "Apple Web Server", "_http._tcp", "local.", "80", "index.html" } }, -}; - -const int gPresetsCount = sizeof( gPresets ) / sizeof( gPresets[ 0 ] ); - -#if 0 -#pragma mark - -#endif - -//=========================================================================================================================== -// main -//=========================================================================================================================== - -int main( int argc, char* argv[] ) -{ - DNSStatus err; - - // Set up DNS Services and install a Console Control Handler to handle things like control-c signals. - - err = DNSServicesInitialize( kDNSFlagAdvertise, 0 ); - require_noerr_string( err, exit, "could not initialize Rendezvous" ); - -#if( __MACH__ ) - signal( SIGINT, SigIntHandler ); -#endif - -#if( defined( WINVER ) ) - SetConsoleCtrlHandler( ConsoleControlHandler, TRUE ); -#endif - - ProcessArgs( argc, argv ); - -exit: - DNSServicesFinalize(); - return( err ); -} - -//=========================================================================================================================== -// Usage -//=========================================================================================================================== - -static void Usage( void ) -{ - fprintf( stderr, "\n" ); - fprintf( stderr, "rendezvous - Rendezvous Tool 1.0d1\n" ); - fprintf( stderr, "\n" ); - fprintf( stderr, " -bbd 'b'rowse for 'b'rowsing 'd'omains\n" ); - fprintf( stderr, " -brd 'b'rowse for 'r'egistration 'd'omains\n" ); - fprintf( stderr, " -bs 'b'rowse for 's'ervices\n" ); - fprintf( stderr, " -lsi 'l'ookup 's'ervice 'i'nstance\n" ); - fprintf( stderr, " -rdb[d] 'r'egister 'd'omain for 'b'rowsing ['d'efault]\n" ); - fprintf( stderr, " -rdr[d] 'r'egister 'd'omain for 'r'egistration ['d'efault]\n" ); - fprintf( stderr, " -rs 'r'egister 's'ervice\n" ); - fprintf( stderr, " -rps 'r'egister 'p'roxy 's'ervice\n" ); - fprintf( stderr, " -rnss 'r'egister 'n'o 's'uch 's'ervice\n" ); - - fprintf( stderr, " -ebs 'e'mulated 'b'rowse for 's'ervices\n" ); - fprintf( stderr, " -ebd 'e'mulated 'b'rowse for 'd'omains\n" ); - fprintf( stderr, " -elsi 'e'mulated 'l'ookup 's'ervice 'i'nstance\n" ); - fprintf( stderr, " -ers 'e'mulated 'r'egister 's'ervice\n" ); - - fprintf( stderr, " -h[elp] 'h'elp\n" ); - fprintf( stderr, "\n" ); - - fprintf( stderr, " -1 Preset 1 (browse for browsing domains) rendezvous -bbd\n" ); - fprintf( stderr, " -2 Preset 2 (browse for AirPort) rendezvous -bs \"_airport._tcp\" \"local.\"\n" ); - fprintf( stderr, " -3 Preset 3 (browse for Xserve RAID) rendezvous -bs \"_xserveraid._tcp\" \"local.\"\n" ); - fprintf( stderr, " -4 Preset 4 (register apple.com domain) rendezvous -rdb \"apple.com\"\n" ); - fprintf( stderr, " -5 Preset 5 (register fake AirPort) rendezvous -rs \"My Fake AirPort\" \"_airport._tcp\" \"local.\" 1234 \"My Fake Info\"\n" ); - fprintf( stderr, " -6 Preset 6 (register fake Xserve RAID) rendezvous -rs \"My Fake Xserve RAID\" \"_xserveraid._tcp\" \"local.\" 1234 \"My Fake Info\"\n" ); - fprintf( stderr, " -7 Preset 7 (register fake web server) rendezvous -rs \"My Fake Web Server\" \"_http._tcp\" \"local.\" 8080 \"index.html\"\n" ); - fprintf( stderr, "\n" ); -} - -//=========================================================================================================================== -// ProcessArgs -//=========================================================================================================================== - -static int ProcessArgs( int argc, char* argv[] ) -{ - DNSStatus err; - int i; - const char * name; - const char * type; - const char * domain; - int port; - const char * text; - size_t textSize; - DNSBrowserRef browser; - DNSResolverFlags resolverFlags; - DNSDomainRegistrationType domainType; - const char * label; - const char * host; - const char * ip; - unsigned int b[ 4 ]; - DNSNetworkAddress addr; - dns_service_discovery_ref emulatedRef; - - // Parse the command line arguments (ignore first argument since it's just the program name). - - require_action_string( argc >= 2, exit, err = kDNSBadParamErr, "no arguments specified" ); - - for( i = 1; i < argc; ++i ) - { - if( strcmp( argv[ i ], "-bbd" ) == 0 ) - { - // 'b'rowse for 'b'rowsing 'd'omains - - fprintf( stdout, "browsing for browsing domains\n" ); - - err = DNSBrowserCreate( 0, BrowserCallBack, NULL, &browser ); - require_noerr_string( err, exit, "create browser failed" ); - - err = DNSBrowserStartDomainSearch( browser, 0 ); - require_noerr_string( err, exit, "start domain search failed" ); - } - else if( strcmp( argv[ i ], "-brd" ) == 0 ) - { - // 'b'rowse for 'r'egistration 'd'omains - - fprintf( stdout, "browsing for registration domains\n" ); - - err = DNSBrowserCreate( 0, BrowserCallBack, NULL, &browser ); - require_noerr_string( err, exit, "create browser failed" ); - - err = DNSBrowserStartDomainSearch( browser, kDNSBrowserFlagRegistrationDomainsOnly ); - require_noerr_string( err, exit, "start domain search failed" ); - } - else if( strcmp( argv[ i ], "-bs" ) == 0 ) - { - // 'b'rowse for 's'ervices - - require_action_string( argc > ( i + 2 ), exit, err = kDNSBadParamErr, "missing arguments" ); - ++i; - type = argv[ i++ ]; - domain = argv[ i ]; - if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) - { - domain = "local."; - } - fprintf( stdout, "browsing for \"%s.%s\"\n", type, domain ); - - err = DNSBrowserCreate( 0, BrowserCallBack, NULL, &browser ); - require_noerr_string( err, exit, "create browser failed" ); - - err = DNSBrowserStartServiceSearch( browser, kDNSBrowserFlagAutoResolve, type, domain ); - require_noerr_string( err, exit, "start service search failed" ); - } - else if( strcmp( argv[ i ], "-lsi" ) == 0 ) - { - // 'l'ookup 's'ervice 'i'nstance - - require_action_string( argc > ( i + 3 ), exit, err = kDNSBadParamErr, "missing arguments" ); - ++i; - name = argv[ i++ ]; - type = argv[ i++ ]; - domain = argv[ i ]; - if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) - { - domain = "local."; - } - fprintf( stdout, "resolving \"%s.%s.%s\"\n", name, type, domain ); - - resolverFlags = kDNSResolverFlagOnlyIfUnique | - kDNSResolverFlagAutoReleaseByName; - err = DNSResolverCreate( resolverFlags, name, type, domain, ResolverCallBack, 0, NULL, NULL ); - require_noerr_string( err, exit, "create resolver failed" ); - } - else if( ( strcmp( argv[ i ], "-rdb" ) == 0 ) || ( strcmp( argv[ i ], "-rdbd" ) == 0 ) ) - { - // 'r'egister 'd'omain for 'b'rowsing ['d'efault] - - require_action_string( argc > ( i + 1 ), exit, err = kDNSBadParamErr, "missing arguments" ); - if( strcmp( argv[ i ], "-rdb" ) == 0 ) - { - domainType = kDNSDomainRegistrationTypeBrowse; - label = ""; - } - else - { - domainType = kDNSDomainRegistrationTypeBrowseDefault; - label = "default "; - } - ++i; - domain = argv[ i ]; - if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) - { - domain = "local."; - } - fprintf( stdout, "registering \"%s\" as %sbrowse domain\n", domain, label ); - - err = DNSDomainRegistrationCreate( 0, domain, domainType, NULL ); - require_noerr_string( err, exit, "create domain registration failed" ); - } - else if( ( strcmp( argv[ i ], "-rdr" ) == 0 ) || ( strcmp( argv[ i ], "-rdrd" ) == 0 ) ) - { - // 'r'egister 'd'omain for 'r'egistration ['d'efault] - - require_action_string( argc > ( i + 1 ), exit, err = kDNSBadParamErr, "missing arguments" ); - if( strcmp( argv[ i ], "-rdr" ) == 0 ) - { - domainType = kDNSDomainRegistrationTypeRegistration; - label = ""; - } - else - { - domainType = kDNSDomainRegistrationTypeRegistrationDefault; - label = "default "; - } - ++i; - domain = argv[ i ]; - if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) - { - domain = "local."; - } - fprintf( stdout, "registering \"%s\" as %sregistration domain\n", domain, label ); - - err = DNSDomainRegistrationCreate( 0, domain, domainType, NULL ); - require_noerr_string( err, exit, "create domain registration failed" ); - } - else if( strcmp( argv[ i ], "-rs" ) == 0 ) - { - // 'r'egister 's'ervice - - require_action_string( argc > ( i + 5 ), exit, err = kDNSBadParamErr, "missing arguments" ); - ++i; - name = argv[ i++ ]; - type = argv[ i++ ]; - domain = argv[ i++ ]; - port = atoi( argv[ i++ ] ); - text = argv[ i ]; - textSize = strlen( text ); - if( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) - { - domain = "local."; - } - fprintf( stdout, "registering service \"%s.%s.%s\" port %d text \"%s\"\n", name, type, domain, port, text ); - - err = DNSRegistrationCreate( 0, name, type, domain, (DNSPort) port, text, (DNSCount) textSize, NULL, NULL, - RegistrationCallBack, NULL, NULL ); - require_noerr_string( err, exit, "create registration failed" ); - } - else if( strcmp( argv[ i ], "-rps" ) == 0 ) - { - DNSHostRegistrationFlags hostFlags; - - // 'r'egister 'p'roxy 's'ervice - - require_action_string( argc > ( i + 7 ), exit, err = kDNSBadParamErr, "missing arguments" ); - ++i; - host = argv[ i++ ]; - ip = argv[ i++ ]; - name = argv[ i++ ]; - type = argv[ i++ ]; - domain = argv[ i++ ]; - port = atoi( argv[ i++ ] ); - text = argv[ i ]; - textSize = strlen( text ); - if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) - { - domain = "local."; - } - - sscanf( ip, "%u.%u.%u.%u", &b[ 0 ], &b[ 1 ], &b[ 2 ], &b[ 3 ] ); - addr.addressType = kDNSNetworkAddressTypeIPv4; - addr.u.ipv4.addr.v32 = (DNSUInt32)( ( b[ 0 ] << 24 ) | ( b[ 1 ] << 16 ) | ( b[ 2 ] << 8 ) | ( b[ 3 ] << 0 ) ); - - fprintf( stdout, "registering proxy service \"%s.%s.%s\" port %d text \"%s\"\n", name, type, domain, port, text ); - - hostFlags = kDNSHostRegistrationFlagOnlyIfNotFound | kDNSHostRegistrationFlagAutoRenameOnConflict; - err = DNSHostRegistrationCreate( hostFlags, host, domain, &addr, NULL, - HostRegistrationCallBack, NULL, NULL ); - require_noerr_string( err, exit, "create host registration failed" ); - - err = DNSRegistrationCreate( 0, name, type, domain, (DNSPort) port, text, (DNSCount) textSize, host, NULL, - RegistrationCallBack, NULL, NULL ); - require_noerr_string( err, exit, "create registration failed" ); - } - else if( strcmp( argv[ i ], "-rnss" ) == 0 ) - { - // 'r'egister 'n'o 's'uch 's'ervice - - require_action_string( argc > ( i + 3 ), exit, err = kDNSBadParamErr, "missing arguments" ); - ++i; - name = argv[ i++ ]; - type = argv[ i++ ]; - domain = argv[ i++ ]; - if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) - { - domain = "local."; - } - fprintf( stdout, "registering no-such-service \"%s.%s.%s\"\n", name, type, domain ); - - err = DNSNoSuchServiceRegistrationCreate( 0, name, type, domain, NULL, RegistrationCallBack, NULL, NULL ); - require_noerr_string( err, exit, "create no-such-service registration failed" ); - } - else if( strcmp( argv[ i ], "-ebs" ) == 0 ) - { - // 'e'mulated 'b'rowse for 's'ervices - - require_action_string( argc > ( i + 2 ), exit, err = kDNSBadParamErr, "missing arguments" ); - ++i; - type = argv[ i++ ]; - domain = argv[ i ]; - if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) - { - domain = "local."; - } - fprintf( stdout, "emulated browsing for \"%s.%s\"\n", type, domain ); - - emulatedRef = DNSServiceBrowserCreate( type, domain, EmulatedBrowserCallBack, NULL ); - require_action_string( emulatedRef, exit, err = kDNSUnknownErr, "create emulated browser failed" ); - } - else if( strcmp( argv[ i ], "-ebd" ) == 0 ) - { - int registrationOnly; - - // 'e'mulated 'b'rowse for 'd'omains - - require_action_string( argc > ( i + 1 ), exit, err = kDNSBadParamErr, "missing arguments" ); - ++i; - type = argv[ i++ ]; - if( strcmp( type, "registration" ) == 0 ) - { - registrationOnly = 1; - } - else if( strcmp( type, "browse" ) == 0 ) - { - registrationOnly = 0; - } - else - { - require_action_string( 0, exit, err = kDNSBadParamErr, "invalid browse type" ); - } - fprintf( stdout, "emulated browsing for %s domains\n", type ); - - emulatedRef = DNSServiceDomainEnumerationCreate( registrationOnly, EmulatedDomainEnumerationCallBack, NULL ); - require_action_string( emulatedRef, exit, err = kDNSUnknownErr, "create emulated domain browser failed" ); - } - else if( strcmp( argv[ i ], "-elsi" ) == 0 ) - { - // 'e'mulated 'l'ookup 's'ervice 'i'nstance - - require_action_string( argc > ( i + 3 ), exit, err = kDNSBadParamErr, "missing arguments" ); - ++i; - name = argv[ i++ ]; - type = argv[ i++ ]; - domain = argv[ i ]; - if( ( domain[ 0 ] == '\0' ) || ( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) ) - { - domain = "local."; - } - fprintf( stdout, "emulated resolving \"%s.%s.%s\"\n", name, type, domain ); - - emulatedRef = DNSServiceResolverResolve( name, type, domain, EmulatedResolverCallBack, NULL ); - require_action_string( emulatedRef, exit, err = kDNSUnknownErr, "create emulated resolver failed" ); - } - else if( strcmp( argv[ i ], "-ers" ) == 0 ) - { - // 'e'mulated 'r'egister 's'ervice - - require_action_string( argc > ( i + 5 ), exit, err = kDNSBadParamErr, "missing arguments" ); - ++i; - name = argv[ i++ ]; - type = argv[ i++ ]; - domain = argv[ i++ ]; - port = atoi( argv[ i++ ] ); - text = argv[ i ]; - textSize = strlen( text ); - if( ( domain[ 0 ] == '.' ) && ( domain[ 1 ] == '\0' ) ) - { - domain = "local."; - } - fprintf( stdout, "registering service \"%s.%s.%s\" port %d text \"%s\"\n", name, type, domain, port, text ); - - emulatedRef = DNSServiceRegistrationCreate( name, type, domain, (uint16_t) port, text, - EmulatedRegistrationCallBack, NULL ); - require_action_string( emulatedRef, exit, err = kDNSUnknownErr, "create emulated registration failed" ); - } - else if( ( argv[ i ][ 0 ] == '-' ) && isdigit( argv[ i ][ 1 ] ) ) - { - // Preset - - ProcessPreset( atoi( &argv[ i ][ 1 ] ) ); - err = 0; - goto exit; - } - else if( strcmp( argv[ i ], "-q" ) == 0 ) - { - // Quiet (no text records) - - gPrintTXTRecords = 0; - } - else if( ( strcmp( argv[ i ], "-help" ) == 0 ) || ( strcmp( argv[ i ], "-h" ) == 0 ) ) - { - // Help - - Usage(); - err = 0; - goto exit; - } - else - { - // Unknown parameter. - - require_action_string( 0, exit, err = kDNSBadParamErr, "unknown parameter" ); - goto exit; - } - } - - // Run until control-C'd. - - #if( __MACH__ ) - CFRunLoopRun(); - #endif - - #if( defined( WINVER ) ) - while( !gQuit ) - { - Sleep( 200 ); - } - #endif - - err = kDNSNoErr; - -exit: - if( err ) - { - Usage(); - } - return( err ); -} - -//=========================================================================================================================== -// ProcessPreset -//=========================================================================================================================== - -static DNSStatus ProcessPreset( int inPreset ) -{ - DNSStatus err; - - require_action_string( ( inPreset > 0 ) && ( inPreset <= gPresetsCount ), exit, err = kDNSBadParamErr, "invalid preset" ); - - err = ProcessArgs( gPresets[ inPreset - 1 ].argc, (char **) gPresets[ inPreset - 1 ].argv ); - -exit: - return( err ); -} - -#if( __MACH__ ) -//=========================================================================================================================== -// SigIntHandler -//=========================================================================================================================== - -static void SigIntHandler( int inSignalNumber ) -{ - DNS_UNUSED( inSignalNumber ); - - signal( SIGINT, SIG_DFL ); - CFRunLoopStop( CFRunLoopGetCurrent() ); -} -#endif - -#if( defined( WINVER ) ) -//=========================================================================================================================== -// ConsoleControlHandler -//=========================================================================================================================== - -static BOOL WINAPI ConsoleControlHandler( DWORD inControlEvent ) -{ - BOOL handled; - - handled = 0; - switch( inControlEvent ) - { - case CTRL_C_EVENT: - case CTRL_BREAK_EVENT: - case CTRL_CLOSE_EVENT: - case CTRL_LOGOFF_EVENT: - case CTRL_SHUTDOWN_EVENT: - gQuit = 1; - handled = 1; - break; - - default: - break; - } - return( handled ); -} -#endif - -//=========================================================================================================================== -// BrowserCallBack -//=========================================================================================================================== - -static void BrowserCallBack( void *inContext, DNSBrowserRef inRef, DNSStatus inStatusCode, const DNSBrowserEvent *inEvent ) -{ - char ifIP[ 32 ]; - char ip[ 32 ]; - - DNS_UNUSED( inContext ); - DNS_UNUSED( inRef ); - DNS_UNUSED( inStatusCode ); - - switch( inEvent->type ) - { - case kDNSBrowserEventTypeRelease: - break; - - case kDNSBrowserEventTypeAddDomain: - fprintf( stdout, "domain \"%s\" added on interface 0x%08X (%s)\n", - inEvent->data.addDomain.domain, - (int) inEvent->data.addDomain.interfaceID, - IPv4ToString( inEvent->data.addDomain.interfaceIP.u.ipv4.addr, ifIP ) ); - break; - - case kDNSBrowserEventTypeAddDefaultDomain: - fprintf( stdout, "default domain \"%s\" added on interface 0x%08X (%s)\n", - inEvent->data.addDefaultDomain.domain, - (int) inEvent->data.addDefaultDomain.interfaceID, - IPv4ToString( inEvent->data.addDefaultDomain.interfaceIP.u.ipv4.addr, ifIP ) ); - break; - - case kDNSBrowserEventTypeRemoveDomain: - fprintf( stdout, "domain \"%s\" removed on interface 0x%08X (%s)\n", - inEvent->data.removeDomain.domain, - (int) inEvent->data.removeDomain.interfaceID, - IPv4ToString( inEvent->data.removeDomain.interfaceIP.u.ipv4.addr, ifIP ) ); - break; - - case kDNSBrowserEventTypeAddService: - fprintf( stdout, "service \"%s.%s%s\" added on interface 0x%08X (%s)\n", - inEvent->data.addService.name, - inEvent->data.addService.type, - inEvent->data.addService.domain, - (int) inEvent->data.addService.interfaceID, - IPv4ToString( inEvent->data.addService.interfaceIP.u.ipv4.addr, ifIP ) ); - break; - - case kDNSBrowserEventTypeRemoveService: - fprintf( stdout, "service \"%s.%s%s\" removed on interface 0x%08X (%s)\n", - inEvent->data.removeService.name, - inEvent->data.removeService.type, - inEvent->data.removeService.domain, - (int) inEvent->data.removeService.interfaceID, - IPv4ToString( inEvent->data.removeService.interfaceIP.u.ipv4.addr, ifIP ) ); - break; - - case kDNSBrowserEventTypeResolved: - { - const uint8_t * p; - const uint8_t * end; - int i; - - fprintf( stdout, "resolved \"%s.%s%s\" to %s:%u on interface 0x%08X (%s)%s\n", - inEvent->data.resolved->name, - inEvent->data.resolved->type, - inEvent->data.resolved->domain, - IPv4ToString( inEvent->data.resolved->address.u.ipv4.addr, ip ), - ( inEvent->data.resolved->address.u.ipv4.port.v8[ 0 ] << 8 ) | - inEvent->data.resolved->address.u.ipv4.port.v8[ 1 ], - (int) inEvent->data.resolved->interfaceID, - IPv4ToString( inEvent->data.resolved->interfaceIP.u.ipv4.addr, ifIP ), - ( inEvent->data.resolved->textRecordRawSize > 0 ) ? " with text:" : "" ); - - p = (const uint8_t *) inEvent->data.resolved->textRecordRaw; - end = p + inEvent->data.resolved->textRecordRawSize; - i = 0; - - if( gPrintTXTRecords ) - { - while( p < end ) - { - uint8_t size; - - size = *p++; - if( ( p + size ) > end ) - { - fprintf( stdout, "\n### MALFORMED TXT RECORD (length byte too big for record)\n\n" ); - break; - } - fprintf( stdout, "%5d (%3d bytes): \"%.*s\"\n", i, size, size, p ); - p += size; - ++i; - } - fprintf( stdout, "\n" ); - } - break; - } - - default: - break; - } -} - -//=========================================================================================================================== -// ResolverCallBack -//=========================================================================================================================== - -static void ResolverCallBack( void *inContext, DNSResolverRef inRef, DNSStatus inStatusCode, const DNSResolverEvent *inEvent ) -{ - char ifIP[ 32 ]; - char ip[ 32 ]; - - DNS_UNUSED( inContext ); - DNS_UNUSED( inRef ); - DNS_UNUSED( inStatusCode ); - - switch( inEvent->type ) - { - case kDNSResolverEventTypeResolved: - { - const uint8_t * p; - const uint8_t * end; - int i; - - fprintf( stdout, "resolved \"%s.%s%s\" to %s:%u on interface 0x%08X (%s)%s\n", - inEvent->data.resolved.name, - inEvent->data.resolved.type, - inEvent->data.resolved.domain, - IPv4ToString( inEvent->data.resolved.address.u.ipv4.addr, ip ), - ( inEvent->data.resolved.address.u.ipv4.port.v8[ 0 ] << 8 ) | - inEvent->data.resolved.address.u.ipv4.port.v8[ 1 ], - (int) inEvent->data.resolved.interfaceID, - IPv4ToString( inEvent->data.resolved.interfaceIP.u.ipv4.addr, ifIP ), - ( inEvent->data.resolved.textRecordRawSize > 0 ) ? " with text:" : "" ); - - p = (const uint8_t *) inEvent->data.resolved.textRecordRaw; - end = p + inEvent->data.resolved.textRecordRawSize; - i = 0; - - if( gPrintTXTRecords ) - { - while( p < end ) - { - uint8_t size; - - size = *p++; - if( ( p + size ) > end ) - { - fprintf( stdout, "\n### MALFORMED TXT RECORD (length byte too big for record)\n\n" ); - break; - } - fprintf( stdout, "%5d (%3d bytes): \"%.*s\"\n", i, size, size, p ); - p += size; - ++i; - } - fprintf( stdout, "\n" ); - } - break; - } - - case kDNSResolverEventTypeRelease: - break; - - default: - break; - } -} - -//=========================================================================================================================== -// RegistrationCallBack -//=========================================================================================================================== - -static void - RegistrationCallBack( - void * inContext, - DNSRegistrationRef inRef, - DNSStatus inStatusCode, - const DNSRegistrationEvent * inEvent ) -{ - DNS_UNUSED( inContext ); - DNS_UNUSED( inRef ); - DNS_UNUSED( inStatusCode ); - - switch( inEvent->type ) - { - case kDNSRegistrationEventTypeRelease: - break; - - case kDNSRegistrationEventTypeRegistered: - fprintf( stdout, "name registered and active\n" ); - break; - - case kDNSRegistrationEventTypeNameCollision: - fprintf( stdout, "name in use, please choose another name\n" ); - break; - - default: - break; - } -} - -//=========================================================================================================================== -// HostRegistrationCallBack -//=========================================================================================================================== - -static void - HostRegistrationCallBack( - void * inContext, - DNSHostRegistrationRef inRef, - DNSStatus inStatusCode, - void * inData ) -{ - DNS_UNUSED( inContext ); - DNS_UNUSED( inRef ); - DNS_UNUSED( inData ); - - if( inStatusCode == kDNSNoErr ) - { - fprintf( stdout, "host name registered and active\n" ); - } - else if( inStatusCode == kDNSNameConflictErr ) - { - fprintf( stdout, "host name in use, please choose another name\n" ); - } - else - { - fprintf( stdout, "unknown host registration status (%ld)\n", inStatusCode ); - } -} - -//=========================================================================================================================== -// EmulatedBrowserCallBack -//=========================================================================================================================== - -static void - EmulatedBrowserCallBack( - DNSServiceBrowserReplyResultType inResult, - const char * inName, - const char * inType, - const char * inDomain, - DNSServiceDiscoveryReplyFlags inFlags, - void * inContext ) -{ - DNS_UNUSED( inFlags ); - DNS_UNUSED( inContext ); - - if( inResult == DNSServiceBrowserReplyAddInstance ) - { - fprintf( stdout, "\"%s.%s%s\" service added emulated\n", inName, inType, inDomain ); - } - else if( inResult == DNSServiceBrowserReplyRemoveInstance ) - { - fprintf( stdout, "\"%s.%s%s\" service removed emulated\n", inName, inType, inDomain ); - } - else - { - fprintf( stdout, "### unknown emulated browser callback result (%d)\n", inResult ); - } -} - -//=========================================================================================================================== -// EmulatedDomainEnumerationCallBack -//=========================================================================================================================== - -static void - EmulatedDomainEnumerationCallBack( - DNSServiceDomainEnumerationReplyResultType inResult, - const char * inDomain, - DNSServiceDiscoveryReplyFlags inFlags, - void * inContext ) -{ - DNS_UNUSED( inFlags ); - DNS_UNUSED( inContext ); - - if( inResult == DNSServiceDomainEnumerationReplyAddDomain ) - { - fprintf( stdout, "\"%s\" domain added emulated\n", inDomain ); - } - else if( inResult == DNSServiceDomainEnumerationReplyAddDomainDefault ) - { - fprintf( stdout, "\"%s\" default domain added emulated\n", inDomain ); - } - else if( inResult == DNSServiceDomainEnumerationReplyRemoveDomain ) - { - fprintf( stdout, "\"%s\" domain removed emulated\n", inDomain ); - } - else - { - fprintf( stdout, "### unknown emulated domain enumeration callback result (%d)\n", inResult ); - } -} - -//=========================================================================================================================== -// EmulatedResolverCallBack -//=========================================================================================================================== - -static void - EmulatedResolverCallBack( - struct sockaddr * inInterfaceAddr, - struct sockaddr * inAddr, - const char * inTextRecord, - DNSServiceDiscoveryReplyFlags inFlags, - void * inContext ) -{ - struct sockaddr_in * ifSin4; - struct sockaddr_in * sin4; - char ifIP[ 64 ]; - char ip[ 64 ]; - - DNS_UNUSED( inFlags ); - DNS_UNUSED( inContext ); - - ifSin4 = (struct sockaddr_in *) inInterfaceAddr; - sin4 = (struct sockaddr_in *) inAddr; - - fprintf( stdout, "service resolved to %s:%d on interface %s with text \"%s\"\n", - IPv4ToString( *( (DNSOpaque32 *) &sin4->sin_addr.s_addr ), ip ), - ntohs( sin4->sin_port ), - IPv4ToString( *( (DNSOpaque32 *) &ifSin4->sin_addr.s_addr ), ifIP ), - inTextRecord ? inTextRecord : "" ); -} - -//=========================================================================================================================== -// EmulatedResolverCallBack -//=========================================================================================================================== - -static void EmulatedRegistrationCallBack( DNSServiceRegistrationReplyErrorType inResult, void *inContext ) -{ - DNS_UNUSED( inContext ); - - if( inResult == kDNSServiceDiscoveryNoError ) - { - fprintf( stdout, "service name registered successfully\n" ); - } - else - { - fprintf( stdout, "service registration failed( %d)\n", inResult ); - } -} - -//=========================================================================================================================== -// IPv4ToString -//=========================================================================================================================== - -static char * IPv4ToString( DNSOpaque32 inIP, char *outString ) -{ - sprintf( outString, "%u.%u.%u.%u", inIP.v8[ 0 ], inIP.v8[ 1 ], inIP.v8[ 2 ], inIP.v8[ 3 ] ); - return( outString ); -} diff --git a/mDNSWindows/Applications/RendezvousTest/ToolPrefixWindows.h b/mDNSWindows/Applications/RendezvousTest/ToolPrefixWindows.h deleted file mode 100644 index eaa6a70..0000000 --- a/mDNSWindows/Applications/RendezvousTest/ToolPrefixWindows.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: ToolPrefixWindows.h,v $ -Revision 1.2 2003/08/20 07:06:34 bradley -Update to APSL 2.0. Updated change history to match other mDNSResponder files. - -Revision 1.1 2003/08/20 06:01:19 bradley -Prefix files for CodeWarrior Windows builds to set compile options. - -*/ - -#ifndef __TOOL_PREFIX_WINDOWS__ -#define __TOOL_PREFIX_WINDOWS__ - -#define DEBUG 0 - -#endif // __TOOL_PREFIX_WINDOWS__ diff --git a/mDNSWindows/Applications/RendezvousTest/ToolPrefixWindowsDebug.h b/mDNSWindows/Applications/RendezvousTest/ToolPrefixWindowsDebug.h deleted file mode 100644 index 1f76fc2..0000000 --- a/mDNSWindows/Applications/RendezvousTest/ToolPrefixWindowsDebug.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - - Change History (most recent first): - -$Log: ToolPrefixWindowsDebug.h,v $ -Revision 1.2 2003/08/20 07:06:34 bradley -Update to APSL 2.0. Updated change history to match other mDNSResponder files. - -Revision 1.1 2003/08/20 06:01:19 bradley -Prefix files for CodeWarrior Windows builds to set compile options. - -*/ - -#ifndef __TOOL_PREFIX_WINDOWS_DEBUG__ -#define __TOOL_PREFIX_WINDOWS_DEBUG__ - -#define DEBUG 1 -#define MDNS_DEBUGMSGS 1 - -#endif // __TOOL_PREFIX_WINDOWS_DEBUG__ diff --git a/mDNSWindows/Applications/RendezvousTest/ToolWin32.mcp b/mDNSWindows/Applications/RendezvousTest/ToolWin32.mcp deleted file mode 100644 index 064aba0..0000000 Binary files a/mDNSWindows/Applications/RendezvousTest/ToolWin32.mcp and /dev/null differ diff --git a/mDNSWindows/Applications/RendezvousTest/ToolWin32VS2002.sln b/mDNSWindows/Applications/RendezvousTest/ToolWin32VS2002.sln deleted file mode 100644 index bc86b75..0000000 --- a/mDNSWindows/Applications/RendezvousTest/ToolWin32VS2002.sln +++ /dev/null @@ -1,24 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 7.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tool", "ToolWin32VS2002.vcproj", "{F66EFE7E-50A6-44D4-87C7-742B303BA852}" -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - ConfigName.0 = all - ConfigName.1 = Debug - ConfigName.2 = Release - EndGlobalSection - GlobalSection(ProjectDependencies) = postSolution - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {F66EFE7E-50A6-44D4-87C7-742B303BA852}.all.ActiveCfg = all|Win32 - {F66EFE7E-50A6-44D4-87C7-742B303BA852}.all.Build.0 = all|Win32 - {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Debug.ActiveCfg = Debug|Win32 - {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Debug.Build.0 = Debug|Win32 - {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Release.ActiveCfg = Release|Win32 - {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/mDNSWindows/Applications/RendezvousTest/ToolWin32VS2002.vcproj b/mDNSWindows/Applications/RendezvousTest/ToolWin32VS2002.vcproj deleted file mode 100644 index d5e1868..0000000 --- a/mDNSWindows/Applications/RendezvousTest/ToolWin32VS2002.vcproj +++ /dev/null @@ -1,185 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mDNSWindows/Applications/RendezvousTest/ToolWin32VS2003.sln b/mDNSWindows/Applications/RendezvousTest/ToolWin32VS2003.sln deleted file mode 100644 index 53a2ba2..0000000 --- a/mDNSWindows/Applications/RendezvousTest/ToolWin32VS2003.sln +++ /dev/null @@ -1,24 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Tool", "ToolWin32VS2003.vcproj", "{F66EFE7E-50A6-44D4-87C7-742B303BA852}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - all = all - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {F66EFE7E-50A6-44D4-87C7-742B303BA852}.all.ActiveCfg = all|Win32 - {F66EFE7E-50A6-44D4-87C7-742B303BA852}.all.Build.0 = all|Win32 - {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Debug.ActiveCfg = Debug|Win32 - {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Debug.Build.0 = Debug|Win32 - {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Release.ActiveCfg = Release|Win32 - {F66EFE7E-50A6-44D4-87C7-742B303BA852}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/mDNSWindows/Applications/RendezvousTest/ToolWin32VS2003.vcproj b/mDNSWindows/Applications/RendezvousTest/ToolWin32VS2003.vcproj deleted file mode 100644 index 2349cb9..0000000 --- a/mDNSWindows/Applications/RendezvousTest/ToolWin32VS2003.vcproj +++ /dev/null @@ -1,205 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/mDNSWindows/DNSServices/DNSServices.h b/mDNSWindows/DNSServices/DNSServices.h index f5be4aa..fbbb2bb 100755 --- a/mDNSWindows/DNSServices/DNSServices.h +++ b/mDNSWindows/DNSServices/DNSServices.h @@ -1310,7 +1310,7 @@ DNSStatus //--------------------------------------------------------------------------------------------------------------------------- /*! @function DNSNoSuchServiceRegistrationCreate - @abstract Creates a registration object and publish the registration to assert non-existance of a particular service. + @abstract Creates a registration object and publish the registration to assert non-existence of a particular service. @param inFlags Flags to control the registration process.