The goal of the Intel Peer-to-Peer Accelerator Kit is to promote the adoption of peer-to-peer designs by providing a set of easy-to-use peer-to-peer enhancements for .NET applications. These enhancements are built on top of the .NET Framework. They include
A set of messaging enhancements that use SOAP and HTTP to transport data on a network. The messaging enhancements are designed to increase reliability, availability, and security in a peer-to-peer application.
Extensions to .NET that allow you to use the messaging enhancements with Remoting and other network classes.
A peer-to-peer daemon (a long-running Windows service) that runs on each peer and facilitates the messaging enhancements features. If you develop multiple peer-to-peer applications with the Intel toolkit, they'll all share the same local service.
Use of a web service for peer discovery. The operation of the web service is completely transparent; you simply host it and configure the clients to be able to locate the server. They'll form peer lookups as required.
An application-level FileCopy API that you can use to transfer files between peers.
Out of this feature set, the last point (the FileCopy API) is probably the least impressive. Although it saves some custom coding work if you need to create a file sharing application, it roughly parallels the type of file transfer approach you would be able to create on your own without too much effort (as described in Chapter 9). The messaging enhancements contain the most useful functionality in the Peer-to-Peer Accelerator Kit, including enhancements that allow you to use Secure Sockets Layer (SSL) automatically, and cross firewall boundaries.
Currently, there are no other .NET products that compete with Intel's Peer-to-Peer Accelerator Kit. Other peer-to-peer platforms exist (notably JXTA, which is usually applied to Java development), but none have a .NET-specific implementation at the time of this writing. For more information about JXTA and to see how its architecture compares to Intel's toolkit, you may want to consider Brendon Wilson's excellent website, which provides a complete JXTA book from New Riders in PDF format. This material is ideal for getting acquainted with a different platform—check it out at http://www.brendonwilson.com/projects/jxta.
The messaging enhancements are the most compelling part of the Intel Peer-to-Peer Accelerator Kit. They include the following:
Store-and-forward. If this is enabled and you attempt to send a one-way message to a peer that appears to be offline, the message will be cached locally and delivery will be attempted later.
Tunnel and relay. This feature allows two peers to communicate over a firewall by sending messages through a relay service.
SSL. As you saw in Chapter 11, it's not possible to use SSL certificate authentication and encryption directly from a peer-to-peer application. Intel's Peer-to-Peer Accelerator Kit solves this problem (with the use of some intensive C++ plumbing).
The messaging enhancements are designed so that they can be easily enhanced in the future. For example, Intel documentation references different methods of firewall traversal such as UPnP NAT and the SOCKS Protocol, which would allow for more flexible handling of peer connectivity. Unfortunately, these solutions aren't implemented in the current (version 1.0) release.
The core piece of technology in the Intel Peer-to-Peer Accelerator Kit is a special Windows service that runs on every peer and handles all communication between computers. This service (shown in Figure 13-1) loads at startup and runs transparently in the background. It acts as a container for all the peer-to-peer services.
It listens for incoming messages and then delivers them to the appropriate application object (in conjunction with the .NET Remoting infrastructure). This is its most important responsibility.
It coordinates peer discovery. It automatically submits peer information to the configured discovery service so that a particular application doesn't need to call a Register() or Login() method.
When delivering messages, it looks up peer location information from the discovery service as required. It also maintains a local cache of peer location information (much as in the Chapter 10 example).
It encrypts and decrypts messages in secure sessions.
It stores messages for later delivery if store-and-forward is enabled.
It sets up a connection with a configured relay server and uses it to avoid firewall or NAT problems. In addition, if configured as a relay server, it routes messages between peers that cannot communicate directly.
It tracks the list of published files (much as in the Chapter 9 example).
Figure 13-2 shows the how the architecture works in a typical application scenario.
You can configure the behavior of the peer service by modifying the settings in its configuration file.We'll cover this topic in detail later in this chapter.
The peer service works by mapping peer URLs to Remoting endpoints. In other words, your application works in terms of abstract peer-to-peer endpoints. These endpoints include information about the remote computer and the remote object and indicate additional information such as whether or not the message should be encrypted before it's sent. The peer-to-peer service translates the peer-to-peer endpoint into that actual Remoting endpoint, and it handles the additional steps that may be required to bypass a firewall or create a secure session, and so on.
So far, you've become well-acquainted with the URL format used by .NET Remoting. It starts with the prefix tcp or http (depending on the protocol used for communication) and indicates the remote application and object. Here's an example:
URLs with the Intel Peer-to-Peer Accelerator look quite a bit different. They start with the prefix peer, which indicates that the message must be handled by the Intel messaging enhancements. The peer URL format is shown here:
The peer name is a dynamic GUID that's generated at install time and uniquely identifies the computer (regardless of the application). The application and object have the same meaning as they do in an ordinary Remoting scenario. Finally, the URL also allows a query string portion that specifies additional parameters. There are currently three parameters you can use:
PeerSecure=True specifies that the communication must be encrypted in an SSL session.
If you've enabled store-and-forward, PeerExpire=<Time> and PeerLive=<Seconds> can set how long a message is retained if the peer is offline.
When using these options, you won't need to modify the URL manually. Instead, you can use the methods provided by the Intel Peer-to-Peer Accelerator Kit classes.
Remember, the underlying transport mechanism is still an HTTP transfer over Remoting. The peer prefix indicates a virtual transportation specification. The peer service translates peer URLs into the actual endpoints, as shown in Figure 13-3.
The discovery service is implemented as a web service that exposes three methods: SetPeer() for adding peer information or updating it, RemovePeer() for removing peer registration, and lookup() for retrieving peer URLs. The peer service handles interaction with the discovery service transparently and caches recently looked-up information to optimize performance.
<PeerInformation> <PeerName>pCDA296F7E06511D1BFD300C04FB12345.peer</PeerName> <URL>http://10.1.1.26:4375</URL> <URL secure="true">https://10.1.1.26:4376</URL> <EntryTime>2001-09-28 18:12:19Z</EntryTime> </PeerInformation>
The timestamp is used to determine which entry to use if multiple registrations are found. When retrieving the peer-connectivity information, the peer service can choose to submit a minimum date, in which case all peer information older than this date will be ignored. The peer service uses this feature intrinsically to retrieve updated information if a message delivery attempt fails.
Despite its promise, the Intel Peer-to-Peer Accelerator Kit isn't without some limitations. For example, when you examine the peer-to-peer messaging application developed later in this chapter, you'll notice that response times are slower than in the original version. Part of this is due to the need to forward all messages through the peer service. Another consideration is the fact that the Intel Peer-to-Peer Accelerator Kit only supports the HTTP Protocol for exchanging data with the relatively verbose SOAP messages, rather than leaner binary messages over TCP. In addition, the revamped application requires some additional considerations that weren't necessary in earlier implementations, and therefore complicate the code.
Another limitation is the reliance on a discovery service. Intel follows the same approach as the examples in this book by using a separate web service to map peer names to connectivity information. However, this means that you need to include a server in your peer-to-peer system as well as a configuration file that tells all peers where to access it. Though an early beta of the Intel Peer-to-Peer Accelerator Kit experimented with broadcasting, it isn't supported in the release version, and hence there's no way to create fully decentralized peer-to-peer applications (although you can configure multiple discovery servers and thereby reduce the burden on a single computer). It's also important to note that the Intel solution for firewall traversal, while useful, is still more rudimentary than that offered by more mature (and far more complex) peer-to-peer applications such as most Gnutella clients. It requires you to provide an available relay and tell the peer where to find it—additional configuration steps that can only complicate life.
Finally, one other potential problem is the way that the Intel Peer-to-Peer Accelerator Kit generates URLs. As you've seen, these don't use fixed endpoints with the machine name or IP address. Instead, they use a GUID. In order for a peer to connect to another, it must know which GUID to use in constructing the URL. Fortunately, the GUID is machine-specific, so you can distribute the GUID for a server endpoint in a client configuration file, much as you would with .NET Remoting. However, this also means that if you want multiple peers to interact (for example, in a chat application), you'll almost certainly need some sort of central component that allows peers to retrieve the URLs of other peers on the system. This component is in addition to the peer-to-peer discovery service, which isn't application-specific. The server component might map user names or e-mail addresses to GUID values, while the discovery service maps these to the required peer-connectivity information.