This chapter explains the different ways that messages are exchanged in BEEP.
In the section Channels in Chapter 2, we saw that the application protocol designer defines a profile that specifies the rules for exchanging messages. Experience shows that these fall into three categories, with each appropriate to a particular set of interaction requirements. It’s up to the application protocol designer to decide which one to use. The three exchange styles are:
The client/server exchange consists of the client sending a message, and the server sending a reply. With the traditional client/server exchange, the peer that acted as the initiator always acts as a client. BEEP doesn’t require this, however—it’s perfectly fine for the peer that’s listening for incoming connections to act as a client once a connection is established.
Because the client/server exchange is so commonplace, we don’t have to look too hard to find a good example to use for the basis of a profile. Perhaps you’re familiar with XML-RPC, a technology that uses XML to encode remote procedure calls (RPCs) that are transmitted over HTTP. The idea is straightforward, and while XML-RPC won’t win any awards for elegance or performance, it gets the job done. The client/server precept is shown in Figure 4-1.
Since no good deed goes unpunished, XML-RPC has evolved into a more generalized messaging protocol called the Simple Object Access Protocol (SOAP). Although a purist might quibble, there are only two architectural differences between XML-RPC and SOAP:
XML-RPC requires the use of HTTP as a transport, while SOAP isn’t HTTP-only.
XML-RPC provides only for request/response remote procedure calls, while SOAP doesn’t explicitly require any particular messaging model.
Oddly enough, SOAP doesn’t have an object model, and still spends a lot of time on marshaling (encoding low-level data structures to a network representation), so it still looks more like RPC than not.
For example, here’s a SOAP message:
<SOAP-ENV:Envelope xmlns:SOAP-ENV='ulink url="http://schemas.xmlsoap.org/soap/envelope/' SOAP-ENV:encodingStyle='ulink url="http://schemas.xmlsoap.org/soap/encoding/'> <SOAP-ENV:Body> <m:GetLastTradePrice xmlns:m='Some-URI'> <symbol>DIS</symbol> </m:GetLastTradePrice> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
If you’re an XML aficionado, this makes perfect sense, obviously! If not, the key take-away is the stuff nested in the
SOAP-Env:Body element. The
m:GetLastTradePrice element looks like a remote procedure call, with one argument,
symbol, having the value
DIS. Another take-away is that the envelope doesn’t contain any addressing information—it doesn’t explicitly identify the network service that will process the call.
The precept shown in Figure 4-2 concisely describes the three things you need to do to define a profile:
Assign a unique identifier for the profile.
Indicate what gets exchanged when a channel is bound to the profile.
Indicate what gets passed back and forth in a client/server exchange.
In BEEP, there’s actually a formal “registration template” that gets filled out when you define a profile. We’ll look at one in a bit, but for now, let’s avoid the formalities and concentrate on the concepts.
The URI part is easy enough; whoever is responsible for http://clipcode.org/ assigned it. (Anyone who can assign a URI can define a profile.) Note that if a URI starts with http://iana.org/, this indicates that the profile has had some review by the IETF. In some cases, this URI-prefix indicates that the profile has been approved for the Internet standards-track.
Similarly, the client/server exchange part is pretty easy too. The request sent by the client is a SOAP message, as is the server’s reply. That’s all BEEP really cares about. But what about the initialization exchange?
When a channel is created, it may require some additional parameters before it can begin normal processing. Many profiles don’t have initialization requirements, but the SOAP profile for BEEP does. In particular, it needs to know:
The identity of the network service that will be processing the SOAP messages
Optionally, whether any special SOAP “features” might be used
Each of these serves a different purpose.
When SOAP runs over HTTP, the network service that consumes the message is identified by two parameters, e.g.:
POST /StockQuote HTTP/1.1 Host: example.com
When SOAP runs over BEEP, you need to convey the same information, but it’s carried a little differently. Recall from Channel Creation in Chapter 3 that BEEP uses the
serverName attribute to identify the virtual host, e.g.:
<start number='1' serverName='example.com'> <profile uri='http://clipcode.org/beep/SOAP' /> </start>
So, what about the part that got sent as HTTP’s
That’s what the
bootmsg used for channel initialization is for. As soon as the channel is started, the client sends a
<bootmsg resource='/StockQuote' />
Actually, using BEEP’s piggybacking feature (see the section The piggyback in Chaspter 3), the
bootmsg probably gets included in the request to start the channel.
If the server likes the resource, then a
bootrpy is sent back; otherwise an error is sent. Once a
bootrpy is received, the client is free to start using the channel to exchange SOAP messages. (Of course, after a
bootrpy is received, if another
bootmsg is sent, an error is returned.)
The short answer is that since BEEP isn’t an application protocol, there’s no such thing. A better answer is that when you design a profile, you should ask yourself whether it makes sense to define a URL scheme for the resulting protocol. In the case of the SOAP over BEEP profile, this makes a lot of sense.
Here’s some examples, all of which should be self-explanatory:
soap.beep://example.com/StockQuote soap.beep://example.com soap.beep://example.com:1026 soap.beep://10.0.0.2:1026
Here are some fun facts about these four examples:
For the first three examples, http://example.com will be used as the
For the last three examples, “\” will be used as the
resourceattribute in the
For the last two examples, the BEEP listener is on TCP port 1026.
But what TCP port is the BEEP listener using in the first two examples? There are two possible choices, depending on whether you prefer using a constant value or you want to let the DNS tell you.
However, the correct answer is always to start by asking the IANA to assign a port number. At this point, ask yourself whether it would be very helpful for the DNS to distribute the load among multiple servers. If not, you’re done! Otherwise, there’s a new DNS record called SRV (RFC 2782) that associates port numbers with services and provides a weighting mechanism for services available on multiple hosts.
For example, a DNS lookup of:
For example, consider these resource records:
$ORIGIN example.com. _soap-beep._tcp SRV 0 1 10288 s1.example.com. SRV 0 1 10288 s2.example.com. SRV 1 0 10288 backup.example.com.
These records say to try to split the load between hosts
s2; if both are unavailable, they specify the
The trick is in understanding the first two numbers after the
SRV. The first number is the priority (the lower the number, the better the priority), and the second number is the weight relative to all other entries with the same priority. Since
s2 have the same, lowest priority number, we look at those first. They each have equal weight, so they should have an equal chance of being selected first. If a connection can’t be made to either, we go to the next highest priority, of which there’s only one entry. So, in the worst case scenario, we’ll try to make three TCP connections.
Here’s a helpful hint if you decide to use SRV records: although you can use any port number you want, you can save yourself a lot of grief by always using the IANA-assigned port number. The reason is that dynamically assigned ports aren’t supported by a lot of infrastructural software, such as packet tracers, firewalls, and the like.
That’s about it for the client/server exchange, but there’s actually a little more to the SOAP over BEEP profile. Because SOAP isn’t tied to a particular messaging model, it actually allows two other exchange styles besides request/response:
Both of these are handled in BEEP by using a one-to-many exchange, as shown in Figure 4-3.
The one thing we didn’t discuss about SOAP is the relationship between SOAP and MIME. As we’ve seen, SOAP is about exchanging envelopes that are encoded using XML. If an envelope needs to contain non-XML information, then the envelope and extra information are sent as a SOAP package. This package is nothing more than a MIME multipart/related object (RFC 2387), e.g.:
Content-Type: multipart/related; boundary="MIME_boundary"; type=application/xml; start="<email@example.com>" --MIME_boundary Content-Type: application/xml Content-ID: <firstname.lastname@example.org> <?xml version='1.0' ?> <SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'> <SOAP-ENV:Body> .. <theSignedForm href='cid:email@example.com' /> .. </SOAP-ENV:Body> </SOAP-ENV:Envelope> --MIME_boundary Content-Type: image/tiff Content-Transfer-Encoding: binary Content-ID: <firstname.lastname@example.org> ...binary TIFF image... --MIME_boundary-- END
Content-ID: header (RFC 2111) is used to identify each component.
Earlier, Figure 4-2 showed an informal description of the SOAP over BEEP profile.
Here’s a copy of the registration for the SOAP over BEEP profile:
- Profile identification
- Messages exchanged during channel creation
- Messages starting one-to-one exchanges
- Messages in positive replies
- Messages in negative replies
- Messages in one-to-many exchange
- Message syntax
SOAP-Env:Envelopeas defined in Section 4 of Simple Object Access Protocol (SOAP) and SOAP Messages with Attachments
- Message semantics
See Simple Object Access Protocol (SOAP)
- Contact information
See the “Authors’ Addresses” section of Using SOAP in BEEP
Although not part of the “formal” template, profile designers often find it useful to include a concise summary, termed a designer doodle, as a comment, e.g.:
SOAP messages, exchanged as application/xml client server reply role message positive negative ====== ======= ======== ======== I bootmsg bootrpy error I or L SOAP-Env:Envelope SOAP-Env:Envelope error
The way to read this is pretty simple:
The initiator sends a
bootmsgand, in reply, gets back either a
Then either the initiator or listener sends an
Envelopeand in reply gets back either an
Although brief, this synopsis leaves out some important things, such as the necessity of a successful
bootmsg before sending a SOAP message. Even so, it does a good job of getting across the ideas behind the exchange.