Digi XBee(R) ANSI C Host Library
Functions

Simple XBee API, TCP sockets over ZigBee. More...

#include "xbee/platform.h"
#include "xbee/byteorder.h"
#include "xbee/sxa.h"

Functions

int _sxa_socket_tx_handler (struct LoopbackHandler __far *lh, ll_Gather *g)
 
int _sxa_socket_rx_handler (const wpan_envelope_t FAR *envelope, wpan_ep_state_t FAR *ep_state)
 
int sxa_socket_init (void)
 

Detailed Description

Simple XBee API, TCP sockets over ZigBee.

An additional layer of functions for the Rabbit/Dynamic C platform. Implements reliable stream-based transport using the Rabbit TCP/IP socket API. The TCP protocol is transformed in order to run between ZigBee endpoints. This relies on custom loopback interface functionality in the Rabbit TCP/IP stack.

How it works:

For an actively opened connection, the socket is opened to 127.1.0.x (where x is the SXA node table index of the desired peer device). Source and destination ports must currently be in the range 61616 to 61871 inclusive, since the port numbers (src and dest) must be packed into a 16-bit field. The field used is the cluster ID, since cluster IDs are otherwise irrelevant for this endpoint.

For a passively opened connection (i.e. listen), port 61616 is opened. Since the socket will receive connections from any interface by default, if you want it to only accept connections over ZigBee, specify the specific interface IF_LOOPBACK when opening it.

As with any other TCP socket, you can use tcp_reserveport(61616) in order to allow queueing of multiple sessions (from distinct peer devices). (Note: you can use other ports as well for listening, up to 61871).

Given a special loopback device packet handler registered with the normal loopback device driver, TCP segments sent to the above address get intercepted and modified to remove most of the 40 odd bytes of IP and TCP header, since this is not required and wasteful given the small MTU of the ZigBee link. The only field in the IP header which is relevant is the destination IP address, which basically indexes the appropriate destination node.

The TCP header is condensed as follows: seqnum: 16 bits acknum: 16 bits flags: 4 bits window: 12 bits These 6 octets become the condensed TCP header in the ZigBee payload for the endpoint.

Sequence numbers are shortened from the normal 32 bits, by assuming that the peers keep track of the implied 16 MSBs. Since no more than a few hundred bytes in the stream could be outstanding on the network, the seq and ack numbers cannot change very much and hence the additional MSBs to make up the full 32-bit seq numbers can be implied. For safety with this truncation scheme, all socket buffers must be 32k or less. Note that the MSBs of the sequence number are supplied in the initial SYN segment, which transports the entire normal TCP header. In order to obviate the need for this level of driver to maintain the high part of the sequence numbers, the TCP socket handler (TCP.LIB) maintains the necessary state information. TCP assumes that truncated sequence numbers are used if the non-standard tcp_FlagTRUNC flag is set in the TCP header. This bit is set by the lower level driver.

Flags supports only SYN,FIN,ACK and RST. Push and URG are not used. RST (if it appears) must be alone or with ACK in order to have its usual TCP meaning. SYN+RST and FIN+RST are reserved for special use like path MTU discovery (TBD).

When the SYN flag is set, no data payload is attached, but the original (uncondensed) TCP header is supplied as the payload.

Window encodes the actual window: when the MSB is zero, the remaining bits encode the window directly, from 0 to 2047 bytes. When the MSB is 1, the LSBs (in the range 1..2047) encode a multiple of 16 bytes in the window (hence encode window 2048..32752). Windows larger than this encode as 100000000000b. When encoding from the true 16-bit window size, the next lower encodable value is used.

When SYN flag is set, no data is allowed, but the full original TCP header is supplied. In particular, the TCP options are parsed just like "real" TCP, although currently the Rabbit only uses the MSS. MSS is used symmetrically, as the minimum of both side's MSS option.

When reconstructing the IP and TCP headers for incoming segments, the library sets the source IP address to a suitable value depending on the peer node e.g. 127.1.0.5 if received from SXA node 5 (in its local node table). The dest IP address is set to 127.1.0.0. All other fields are reconstructed in a reasonable manner, except that IP and TCP checksums are not generated. It is assumed to be superflous given the ZigBee frame CRCs.

Determining the path MTU can be tricky. For now, it is set to 104 octets, (default definition of SXA_SOCKET_MTU, which can be overridden), but with IP and TCP header compression, this results in a TCP MSS of 64 octets. Better throughput may be obtained by experimentation. It is imperative with TCP to avoid fragmentation at lower layers.

Todo:
Need a better path MTU discovery mechanism.