Design
A typical nuggets user will run both a client and server program. Whether or not these are run in two threads or two processes shouldn't matter.
Server
The server first registers the nuggets service with the underlying bluetooth implementation. This step actually happens in the same function call that accepts a connection, but it becomes important in the client. Next the server attempts to read the first 16 bytes (this should be the hash) of a file that would contain this client's nugget if we already had it.
Once a connection is accepted, the server receives a length, a hash, and a nugget. The length is a 4 byte big-endian representation of the nugget length. The hash is an MD5 hash of the nugget. The nugget... well, nobody knows what they put in nuggets - that's why we have to get the length.
Upon receiving the fixed-length quantities, the server compares the hash sent by the client with the hash read from the file. If they are identical, the server closes the connection immediately. If the nugget were something large (multimedia), this would save you the work of receiving all packets after the first one if you didn't need to.
If the server does choose to receive the nugget, it does so. It then writes to a file (uniquely named for that client) the recently received hash followed by the actual nugget. The server signals receipt of the nugget by sending an empty packet to the client. If the client doesn't wait for this empty packet, it frequently closes the connection before the server can receive the entire nugget.
Client
Ideally, the client program registers to be called back whenever a new bluetooth device is discovered and then sleeps indefinitely. On device discovery, the client creates a new thread which searches that device for nuggets and, upon finding the nuggets service, exchanges nuggets with it.
In reality, the Impronto SDK's implementation of device discovery eventually decides that it has found all the devices it's going to find. It also caches previously-found devices so that it can return them immediately upon later discovery requests. To account for this, the client keeps a 5 element list of recently discovered devices and doesn't service-search them when the discovery reports their existance. To account for the immediate termination of discoveries due to the caches, the client sleeps for 5 seconds after any discovery finishes.
The client first reads it's nugget from a file and calculates the hash and the nugget length. This is done per-connection. The client first sends a 4 byte nugget-length, then a 16 byte hash of it's nugget, then sends the actual nugget. After sending, the client waits for a single packet from the server indicating it has received the entire nugget.
This design minimizes power consumption. Note that the client and server both sleep for the majority of their runtime. Also, when handling large nuggets, only one packet is transmitted unless the server actually needs the nugget. Overhead for control traffic is only one empty packet. These optimizations also conserve power by minimizing the use of the bluetooth transmitter.