OBEX (Object Exchange) is a binary protocol designed to allow a variety of devices to exchange data simply and spontaneously. Spontaneity is important for Bluetooth, where short duration ad-hoc connections can be set up.
OBEX has a client/server architecture, and allows a client to push data to a server or pull data from a server. For example, a PDA might pull a file from a laptop, or a phone synchronising an address book might push it to a PDA.
The Infrared Data Association (IrDA) is a non profit organisation which created the IrDA standards that specify how to connect and transfer data across infrared links. OBEX is an IrDA specification. The IrDA has similarities to the Bluetooth SIG in that both have an international membership, and both create and promote communication specifications. More details on IrDA can be found at http://www.irda.org. The IrDA specifications can be downloaded from this site.
IrDA and Bluetooth both support short range, ad-hoc links. IrDA supports higher data rates than Bluetooth, and also has higher layers in the stack than Bluetooth (see Chapter 26 for more details on how IrDA compares with Bluetooth). The similarities between the two communications protocols’ lower layers mean that IrDA’s OBEX protocol is ideally suited to transferring objects between Bluetooth devices. This is one reason why the Bluetooth core promoters decided to adopt OBEX from IrDA. Another reason is that adopting existing standards means there is a larger base of available support for the standard, and of course, adopting an existing working standard is less work and lower risk than “reinventing the wheel.”
The OBEX definition includes:
The OBEX definition can be downloaded from the Infrared Data Association’s Web site. In addition to the parts above, it also includes an application framework, examples of OBEX exchanges, details of how to implement OBEX with other IrDA specifications, and test guidelines.
Figure 13–1 shows the IrDA DATA stack (there is also an IrDA standard for control) and the Bluetooth protocol stack with OBEX. The two stacks have many parallels:
Bluetooth’s OBEX is the same as IrOBEX (OBEX is just short for IrOBEX). OBEX provides object exchange services similar to hypertext transfer protocol (htttp), allowing arbitrary data objects to be exchanged between devices.
In the IrDA DATA protocol stack, OBEX can use IrCOM and Tiny TP. The Blue-tooth specification does not require these elements of the IrDA DATA stack, but allows for implementations which support them. It is left up to implementers to decide whether to implement these layers.
The Bluetooth specification defines a series of rules for how Bluetooth devices handle OBEX over RFCOMM:
OBEX packets are carried in RFCOMM frames. The data part of an RFCOMM frame is just an undifferentiated byte stream, so the receiving OBEX implementation must sort this byte stream into packets. This should not be difficult because all OBEX packets include a length field, which can be used to figure out where one packet finishes and the next one starts.
Bluetooth specification 1.0 and 1.1 does not specify how to map TCP/IP over Bluetooth links; however, it does give some rules for mapping OBEX over TCP/IP.
When an OBEX server using TCP/IP starts up, it should initialise its TCP port and register with the service discovery database. When an OBEX client using TCP/IP starts up, it discovers the server’s SDP information, initialises a socket (with a number higher than 1023), and establishes a connection to the OBEX server’s host. The client then sends an OBEX connect request to the server as described in Section 13.3.3.
To disconnect, the client sends the disconnect request and closes the TCP port.
Applications which are going to exchange data need to agree on a standard way of representing it. The object model fills this need by defining a series of headers which can hold data objects and information about them.
Each header carries a piece of information about the object, or in the case of body headers, it can carry the object itself. Figure 13–2 shows the structure of a header: it begins with a single-byte Header ID (HI), which says what information is in the rest of the header and how it is formatted. This is followed by the header value, which is a byte or more of information.
Bits 7 and 8 of the Header ID describe the format of the data in the header value. The choice of formats is:
Objects do not have to use headers. If two applications know exactly what data they are going to exchange, then headers might not be needed. However, they are available for applications which want to use them.
The type of the header is carried in bits 1 to 6 of the header ID. There are sixteen types of headers defined in version 1.2 of OBEX:
Connection IDs and targets both identify the destination of the headers. Since they fulfill the same purpose, one or the other is used; they are never both used together.
Application parameters, authentication challenges, and authentication responses use an extra layer of structure to carry information. They send triplets of tag, length, and value. The tag and length fields are each one byte, and the value can be up to 255 bytes long. The tag values identify the parameters being passed and are defined by the applications or protocol layers which will use the values. This means that tag values do not have the same meaning to other applications or protocols.
Because each of the headers has its own Header ID, they can be sent in any order, and they will still be interpreted correctly. The connection ID is an exception to this rule, since it says which one of several multiplexed connections the object is being sent on. It must be the first header, so the system knows where to direct the rest of the headers.
In addition to the list above, the range from 0x30 to 0x3F has been reserved for user defined header IDs. Of course these should be used with care, as different systems will interpret them differently; however, the user defined headers provide complete freedom for application developers to transfer data types which are not covered by the standard OBEX headers.
The OBEX session protocol describes how two OBEX clients and servers can communicate by exchanging request and response messages. The client sends requests and the server sends responses.
Requests are sent as packets. The structure of a request packet is shown in Figure 13–3. Each packet starts with a single byte OpCode which identifies the type of request in the packet. This is followed by a two byte packet length sent high byte first. Finally, the request has one or more headers (as described in Section 13.2).
Because of the two byte length field, the maximum length of a packet is 65535 bytes, and the packet length on a particular connection may be negotiated to a shorter value. This means that large requests may not fit in one packet, so it is possible to split a request across several packets. If a request is split across several packets, the most significant bit of the OpCode is used as a continuation flag. The most-significant bit of the OpCode is set to 1 for the last packet in the request, and set to 0 for all other packets in the request.
Responses have a similar structure to requests as shown in Figure 13–4. A one byte code identifies the type of the response, and again there is a two byte length field. Responses can be split into several packets, with one response packet being sent for every request packet received.
The response code has an http status code in the seven least significant bits. The most significant bit of the response code is called the final bit and is always set to 1; this lets the client know that it can send another request packet.
The response data can include headers and objects, or other application-specific data. It is possible for a response to carry no data at all; in this case, the response code carries all the information needed to interpret the response, and the length field is set to 3.
When the client sends a request packet with part of a request which will be continued in other packets, the server will usually reply with a “continue” response code (0x10). When the client sends a request packet with the final part of a request, the server will usually reply with a “success” response code (0xA0). The OBEX protocol specification defines a series of other response codes which can be used by the server to indicate various actions and errors.
OBEX defines six different operations; these (with their OpCodes) are:
In addition, a range of OpCodes are reserved from (0x10 to 0x1F) for user defined operations. As always with user defined elements, care should be taken as these could be misinterpreted by some devices. Versions 1.0 and 1.1 of the Bluetooth specification say that user defined OpCodes will not necessarily be adopted when OBEX is used over Bluetooth.
Before a Bluetooth device can start an OBEX session, it must know the correct RFCOMM channel to use. The OBEX client sends SDP requests to the server to find out information on the OBEX server. The OBEX client then establishes an RFCOMM channel to the OBEX server using the channel number given in the OBEX server’s service record.
Next, an OBEX session is started by the client sending a connect request. The connect request contains the parameters for the session. The server accepts the request by sending a response with response code = success. Any other response rejects the connection.
The session will remain in place until it is deliberately disconnected by the client, or until some sort of failure causes it to be shut down; for example, if one device goes out of range and the underlying ACL link times out.
Figure 13–5 illustrates the various stages in a client setting up an OBEX session over a Bluetooth link.
The structure of the connect request is shown in Figure 13–6. It begins with the OpCode and packet length common to all OBEX requests.
The third byte of the connect request gives the version of OBEX which the client proposes to use for the session. The Bluetooth version 1.0 and 1.1 specifications reference version 1.2 of OBEX, so Bluetooth devices should be capable of handling this version of OBEX, and this should be the default type for a connect message. The version number is encoded with the major version (1) in the four most significant bits and the minor version (.2) in the four least significant bits. So, version 1.2 is represented as 0x12.
In version 1.2 of OBEX, the flag bits in a request are all reserved; they should be set to 0 by the client and ignored by the server.
The maximum OBEX packet length a client can receive can be used to restrict the length of packets to a value less than the maximum defined by OBEX (OBEX’s maximum packet length is limited by the two-byte packet length field to 65535). The maximum packet length should never be set to less than 255 bytes, otherwise requests and responses which have to be sent in a single packet might not fit.
Optionally, other headers can be sent in the connect request packet, but the connect request is not allowed to be split across more than one packet, so this may limit the headers which can be sent.
Count and length headers may be used to indicate how much data will be sent during the session. Target or who headers may be used to indicate where to send the data. Description headers may be used to describe the connecting device or service.
A server is allowed to discard headers which it does not understand; in particular, it may not understand user defined headers. Because all headers have a standard format for their format and length, devices should be able to interpret enough of any header to figure out how long it is so that it can be cleanly discarded without affecting other headers in the packet.
The structure of the response to a successful connect request is shown in Figure 13–7. Any response code other than success (0xA0) means that the request has not succeeded. The response code and packet length follow the common format used by all OBEX packets. The version number is encoded in the same way as in the connect request, and should also indicate version 1.2 for OBEX on Bluetooth 1.0 and 1.1 implementations.
Bit 0 of the flag field is used to indicate that multiple OBEX connections can be handled. The rest of the response flags are reserved and should be set to 0 by the sending server and ignored by the receiving client.
The maximum packet length limits the size of the packet the server is willing to accept; this is not necessarily the same as the length the client was willing to accept.
The optional headers can include a description header, which describes the device or service handling the connection. If the connect fails, the optional headers can include a description header, which gives more information on why it failed.
It is possible to use OBEX commands to transfer objects even if a connect request has not been sent, although if this is done, there is no guarantee that opposite ends of the link are using compatible settings. If default values are being used, a maximum packet length of 255 bytes should be assumed since all implementations should be able to handle these size packets.
A client can shut down an OBEX session with a disconnect request as shown in Figure 13–8. If a disconnect message is sent, it contains the usual OpCode and packet length, and optionally can contain more headers describing why the link is being shut down.
A disconnect message cannot be refused, so the server should always respond with a packet containing the response code “success.”
The Bluetooth core specification says that a disconnect message should be sent to close down an OBEX session. However, a session can also be shut down just by closing down the underlying links. This may happen if a device moves out of range, so all Blue-tooth implementations must be able to terminate OBEX sessions if underlying links are shut down.
A put request is used to send an object from a client to a server. Usually, the put request will include name and length headers, as well as a body header for the data.
For a small object, a put request may fit into one packet. Figure 13–9 shows a message sequence chart where this is the case. The client sets the final bit to indicate that this is the last packet in the request, and sends the put request, including the object, in an end of body header. The server replies with a response containing the response code “success” to indicate that it has accepted the object.
Objects such as files may not fit in one request packet. In this case, the client will send a series of put request packets as shown in Figure 13–10. All the put request packets except the final one will have a chunk of the object sent in a body header. The final packet puts the last chunk of the object in an end of body header. The final flag in all the put requests except for the last one is set to 0 to indicate that there is more of the request to come. The last packet in the put request is set to 1 to indicate that it is the end of the put request.
The server responds to put requests which do not have the final flag set with continue responses. When the server receives a put request with the final flag set, it responds with success (assuming there have been no errors in the transfer). All response packets have the final flag set to 1, regardless of whether they are responses to put requests which will be continued or to the final put request.
The put request can use any OBEX headers to describe the object being sent to the server. These should come before the body headers so that the server knows what sort of object it is using before it gets the object (although it is only mandatory for name and type headers to precede the body, an awkward implementer could choose to send other headers after the body).
The client can use target and type headers to suggest what the server should do with the object being sent, but it is entirely up to the server whether it chooses to obey those suggestions.
The server can use a setpath operation to suggest a directory into which objects will be transferred. This is particularly useful if a whole hierarchy of files and folders is being transferred. Setpath can be used to create a directory, then put places objects in the directory. However, again the server could choose not to follow the directions. For instance, it is common for all received objects to be placed in a directory labeled “incoming.” In systems which do this, if a client specified the directory /etc/bin, the result would be to put files in incoming/etc/bin.
A put request without any body or end of body headers puts a non-existent object on the server. If an object with the specified name exists in the current working directory, then that object is deleted. Devices are not required to support delete operations.
A put request with an empty end of body header creates an empty object; for instance, this might be used to create an empty file.
The get operation is used to request an object from the server. A get request begins with the OpCode (0x03) and two bytes of packet length. Then there are optionally a series of headers giving information about the object to get. Usually, a name header would be included to specify which object to get; however, it is possible that some applications may only ever get one object, in which case, as long as both sides know this, there is no need to specify a name.
As Figure 13–11 shows, the server replies with the return code “success” if it accepts the get. If the object is small enough to fit in a single OBEX packet, the server also sends the requested object in an end of body header in the response packet.
As for get requests, it is possible that the requested object will not fit into a single OBEX packet. In this case, the server sends a continue response with part of the object in a body header. The client keeps sending get requests until it receives a success response, indicating that it has the final part of the object as shown in Figure 13–12.
Note that the final flag in every response is set to 1. Unless the client continues to send get requests, the transaction will finish.
It is possible to get default objects of certain types; for example, a default business card or a default Web page. In this case, the full details of the object would not have to be specified in the get request’s headers.
OBEX (Object Exchange) is a protocol for transferring data objects between devices that Bluetooth has adopted from the Infrared Data Association (IrDA) specifications.
OBEX defines a session protocol which is used to send requests from a client to a server. The server replies with responses. Both requests and responses are sent in packets.
OBEX packets can contain various headers which describe data, and body headers which contain chunks of data.
OBEX can specify a particular service or protocol which receives data objects, and can also specify a directory in which objects such as files should be placed. Although it is up to the device receiving files where to put them, it is not forced to follow the path suggestions of the sending device. For example, if a sender asks for a file to go in the Windows directory, the receiving device could choose to put the file in a directory called incomingWindows. This allows a user to “quarantine” files in an area where they can be checked before they are put into use.
The Bluetooth specification references version 1.2 of the OBEX specification, which was written in March 1999.
13.59.11.18