Includes a slightly modified version of the python plist library to allow syndication of data from Google App Engine to the iPhone via xml plists.
Includes a generically useful caching plist downloader library for the iPhone SDK that keeps the user in sync with Google App Engine data and allows offline access to that data.
isonnet, a Google App Engine application that syndicates Shakespeare's Sonnets in plist form for consumption by the iPhone app.
Sonnet, a viewer application for the iPhone, which we're going to release soon for free on the app store, that connects to our Google App Engine site to download, cache, and display Shakespeare's Sonnets.
Future Features / Informal Roadmap
Authentication with Google App Engine with the user's Google ID
Two-way communication and data sync between app engine and the iPhone SDK
Integration and automatic plist syndication of underlying Google App Engine Data Storage and objects
Support for Application skinning through plist syndication
Support for storage of the iPhone user's application preferences on Google App Engine.
Reverse DNS via the usual OS X means doesn't seem to work on the iPhone. It looks like this is a known bug/limitation. The new apple developer forums (login required) have a thread that's dedicated to the problem. (rdar://problem/5929766 is mentioned there). Apple seems to have used the eraser on some other of their DNS code on the iPhone. Saurik has an interesting hack to work - around a perhaps related change in DNS behavior.
You can actually get reverse DNS lookup on the iPhone to work using res_query (which is in libresolv, so make sure you link against libresolv.dylib) to query DNS and dns_parse_packet, which you'll find in dns_utils.h, to do the work of parsing out the DNS server reply works rather well. I could not get the recommended tools in dns.h to work, but I did discover that res_query returns the same raw reply from the DNS Server that dns_parse_packet expects from the utilities in dns.h. The code:
#define T_PTR 12 /* domain name pointer */
#define C_IN 1 /* the arpa internet */
static const int kBufLen = 1500;
//takes a string like 126.96.36.199.in-addr.arpa and turns it into the hostname
char *_reverseDns(const char* arpaPoint)
int len = -1;
int queryType = T_PTR; /* domain name pointer */
int arpanet = C_IN; /* the arpa internet = 1*/
len = res_query(arpaPoint, arpanet, queryType, (u_char *)buffer, kBufLen);
if (len > 0)
reply = dns_parse_packet(buffer, len);
resStr = ((*(reply->answer))->data).PTR->name;
fprintf(stderr, "Error, res_query() error value: %d\n", errno);
if (61 == errno)
resStr = "Could not connect to DNS";
resStr = "DNS entry Not Found";
//makes 192.168.1.1 into 188.8.131.52.in-addr.arpa
NSString *makeDNSLookupString(NSString *inString)
NSString *eachString = @"";
NSScanner *scanner = [NSScanner scannerWithString:inString];
NSUInteger scanLocation = 0;
NSUInteger stringLen = [inString length];
NSString *outStr = @"";
while([scanner scanUpToString:@"." intoString:&eachString])
eachString = [eachString stringByAppendingString:@"."];
outStr = [eachString stringByAppendingString:outStr];
scanLocation = [scanner scanLocation];
if (scanLocation < stringLen)
[scanner setScanLocation:scanLocation + 1]; // hop the . character
outStr = [outStr stringByAppendingString:@"in-addr.arpa"];
NSString *reverseDNS(NSString *ipAddress)
NSString *arpaString = makeDNSLookupString(ipAddress);
//NSLog(@"arpaString = %@", arpaString);
NSString *returnString = [NSString stringWithCString:_reverseDns([arpaString cStringUsingEncoding:NSASCIIStringEncoding]) encoding:NSASCIIStringEncoding];
You can find a simple example app that uses this here.
It also uses a nice trick from The iPhone Developer's Cookbook. It's MIT licensed, so feel free to use it in your own app. Consider this a workaround until apple comes up with something simpler. This works for me installed on the iphone itself looking up addresses on the internet and on my local network (it loses the .local, but is otherwise aok). It doesn't validate the ip address string you give it or check to see if DNS is even available, so you'll want to wrap it in some reachability and validation calls, etc (which I did not do in the demo app, but it fails fairly gracefully when you give it garbage input).
Running reverseDNS(@"192.168.1.139") (which is the IP address of my imac) on the iPhone connected via wi-fi to my local network returns @"FreakinIMac" (which is the host name of my imac). It even returns the DD-WRT hostname of my router. It returns @"DNS entry Not Found if it can't find an entry or errs out and it will log errno if set by res_query to the console. You'll probably want to wrap some error handling code around this if you plan to use it in a real app.
Other useful stuff:
You can find the source for libresolvhere, which was quite
helpful. The source to dns.c and dns_util.c proved useful as well. A post on an apple mailing list also pointed me in a direction. Having the source to the libraries you use is a great help. Thanks to Apple for making these available; keep 'em coming!
Note: If you want to log the whole parsed reply from the DNS server, use dns_print_reply (also in dns_utils) with DNS_PRINT_ANSWER as an arg. There is probably a lot more you can do with this method of DNS lookup. I'm guessing you can send pretty much any kind of DNS query and parse the result, just watch out for (and apply his genius patch, if necessary) that bug that Saurik found.
Note: Watching network traffic with a packet sniffer like Wireshark is quite informative.