SFBPacket.h File Reference

Packet structure and access methods. More...

#include "SFBTypes.h"
#include "SFBAssert.h"

Include dependency graph for SFBPacket.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PacketHeader
 The information associated with a packet, when it is stored in memory only -- there is no preestablished packet header on the wire. More...

Defines

#define PFSC_END   ((u8) '\012')
#define PFSC_ESC   ((u8) '\333')
#define PFSC_EEND   ((u8) '\334')
#define PFSC_EESC   ((u8) '\335')
#define CHECK_BYTE_INIT_VALUE   (0xF0)
#define CHECK_BYTE_UPDATE(v, d)   ((v) = ((v<<1)|((v>>7)&1))^d)
#define API_ASSERT_VALID_PACKET(u8ptr)   API_ASSERT(validPacket(u8ptr),E_API_INVALID_PACKET)
const PacketHeaderpacketHeaderInternalUnsafeConst (const u8 *packet)
 Low-level packet handling methods.
PacketHeaderpacketHeaderInternalUnsafe (u8 *packet)
bool packetEqual (const u8 *packet1, const u8 *packet2)
 Check if two packets have the same content.
u8 packetLength (const u8 *packet)
 Access the length of packet.
u8 packetReadLength (const u8 *packet)
 Access the 'read length' of packet.
u8 packetFlags (const u8 *packet)
 Access the flags of packet.
u8 packetSource (const u8 *packet)
 Access the source of packet.
u8 packetCursor (const u8 *packet)
 Access the read cursor of packet.
bool packetCheckByteValid (const u8 *packet)
 Determine if packet ends with a valid 'check byte'.
bool validPacket (const u8 *packet)
void packetReread (u8 *packet, u32 newIndex=0)
 Set the value of the 'read cursor' within packet to be newIndex, or to packetLength(const u8 *), whichever is smaller.
bool packetRead (u8 *packet, int &result, int code=DEC, u32 maxLen=MAX_PACKET_LENGTH)
 Starting from packetCursor() of packet, consume no more than maxLen bytes to read an integer, in one of a variety of formats specified by code, and store the read value into result.
bool packetRead (u8 *packet, u32 &result, int code=DEC, u32 maxLen=MAX_PACKET_LENGTH)
 Starting from the packetCursor() position, attempt to read a number into result, in the format specified by code, from packet.
bool packetRead (u8 *packet, u64 &result)
 Starting from the packetCursor() position of packet, read a big-endian network order u64 into result.
bool packetRead (u8 *packet, u8 *result, u32 length)
 Starting from packetCursor() of packet, read exactly length bytes into buffer, advancing packetCursor() by length, and return true.
bool packetReadCheckByte (u8 *packet)
 Attempt to read a valid chack byte from the current position of packet.
bool packetReadEOF (u8 *packet)
 Have we read to the end of packet?
bool packetReadPacket (u8 *packet, u8 *&subpacket)
bool zpacketPrefix (u8 *packet, const char *to)
 Determine if packet begins with the sequence of non-null bytes given by to.
u8makePacket (u8 *buffer, u32 bufferLength, u8 face, const char *packetData)
u8makePacket (u8 *buffer, u32 bufferLength, u8 face, const u8 *packetData, u32 packetDataLength)


Detailed Description

Packet structure and access methods.

Author:
David H. Ackley.
Date:
(C) 2009 All rights reserved.
Code License:
The GNU Lesser General Public License
License Note:
All code samples shown in documentation are placed into the public domain.

Function Documentation

bool packetCheckByteValid ( const u8 packet  ) 

Determine if packet ends with a valid 'check byte'.

A packet check byte is generated by calling facePrintlnCheckByte() or by using the "%\n" format code in facePrintf(); it is a single byte 'summary' or 'digest' of the all the rest of the packet content that precedes it.

A packet may or may not end with a check byte, depending on how it was generated. Although it is a mistake to call this method on a packet that does not contain a check byte, it is up to the programmer to avoid it and this mistake is not detected by the SFB library; the return value of such a call will usually be false, but might, simply by bad luck, be true.

Note that this method ignores the packetCursor(); it always checks the entire packet contents.

Parameters:
packet The packet to examine for possessing a valid check byte.
Returns:
true if packet has a valid check byte; false if the packetLength() is zero or the final byte is not a valid check byte for the rest of packet.
Blinks:
E_API_INVALID_PACKET if packet is null or pointing at something that is detectably corrupt or not a packet.
Example:
    void myHandler(u8 * packet) {
      if (!packetCheckByteValid(packet)) // Not doing API_ASSERT_TRUE(packetCheckByteValid(packet)) --
        return;                          // Who knows what the world might send us?  Just ignore bogons..
      println("valid packet");
      ...
    }
    void setup() {
      reflex('h',myHandler);
    }
    void loop() {
      pprintf("hello world%\n");     // The %\n adds the check byte!
      delay(1000);
    }

u8 packetCursor ( const u8 packet  ) 

Access the read cursor of packet.

Each packet has an internal cursor value indicating how much of the packet has been read (e.g., by packetRead() or packetScanf()); this method accesses that value. A cursor value of 0 means the cursor is before the first byte, and so the first byte will next be read, and a cursor value of packetLength() means the cursor is after the last byte, so no more bytes can be read and packetReadEOF() will be true.

Note that packetReread() can be used to modify the cursor value of a packet.

Parameters:
packet The packet whose cursor position is needed
Returns:
from 0 to packetLength(u8 * packet).
Blinks:
E_API_INVALID_PACKET if packet is null or pointing at something that is detectably corrupt or not a packet.
Examples:
zformat2.cpp, and zformat3.cpp.

bool packetEqual ( const u8 packet1,
const u8 packet2 
)

Check if two packets have the same content.

Considers only the lengths and content of the packets; any possible differences in their packetSource(), packetFlags(), and/or packetCursor() are ignored.

Returns:
true if the packet1 and packet2 are the same length and all packetLength() bytes match; false otherwise
Blinks:
E_API_INVALID_PACKET if packet1 or packet2 is null or points at an invalid packet.
Since:
0.9.9

u8 packetFlags ( const u8 packet  ) 

Access the flags of packet.

Non-zero packet flags generally, though not necessarily, correspond to various error conditions, and by default packets with errors will _not_ cause reflex triggering, so in the simplest packet handling circumstances, the return value from this function will typically be 0.

Parameters:
packet The packet whose flags are to be read.
Returns:
a bitwise-OR of these possible flag values: PK_DELETED, PK_OVERRUN, PK_PARITY, PK_BREAK, PK_BUFFER, PK_BAD_ESCAPE.
Blinks:
E_API_INVALID_PACKET if packet is null or pointing at something that is detectably corrupt or not a packet.
Example:
    void myAHandler(u8 * packet) {                     // 'Broken' packets not delivered to normal handlers..
      API_ASSERT_ZERO(packetFlags(packet)&PK_BROKEN);  // ..so none of those packet flags can be set.
      ...
    }
    void myBHandler(u8 * packet) {                     // But here we've specially requested broken packets.
      if (packetFlags(packet)&PK_BROKEN)               // ..so this 'if' condition might be true
        println("WARNING!  Packet with errors received");
      ...
    }
    ...
    void setup() {
      reflex('a', myAHandler);      // Define a normal reflex
      reflex('b', myBHandler, SFBReactor::TRIGGER_SPINE, true);  // Final 'true' arg says include broken packets

u8 packetLength ( const u8 packet  ) 

Access the length of packet.

Parameters:
packet The packet whose length is needed
Returns:
from 0 to MAX_PACKET_LENGTH
Blinks:
E_API_INVALID_PACKET if packet is null or pointing at something that is detectably corrupt or not a packet.
Example:
    void myHandler(u8 * packet) {
      print("I received a packet of length ");   // Start a packet with a fixed message
      println(packetLength(packet), DEC);        // End it with a number in decimal
    }
Examples:
forward.cpp, qled1.cpp, sdcard3.cpp, and tee.cpp.

bool packetRead ( u8 packet,
u8 buffer,
u32  length 
)

Starting from packetCursor() of packet, read exactly length bytes into buffer, advancing packetCursor() by length, and return true.

If packetReadLength() of packet is less than length return false and leave packet and buffer unchanged.

Parameters:
packet The packet to read.
buffer A non-null pointer to at least length bytes of writable space.
length How many bytes to read.
Returns:
true if length bytes were read and stored in buffer; false if no such number can be read from the current position, either because an input unsuitable for code is seen first, or because the end of the packet is reached first.
Blinks:
E_API_INVALID_PACKET if packet is null or pointing at something that is detectably corrupt or not a packet.
Blinks:
E_API_NULL_POINTER if buffer is null.
Side Effects:
If true is returned, the packetCursor() of packet is advanced by length bytes, and length bytes are written to buffer.
Since:
0.9.10

bool packetRead ( u8 packet,
u64 result 
)

Starting from the packetCursor() position of packet, read a big-endian network order u64 into result.

Reads values output by facePrintBinary(u8 face,u64 value).

Parameters:
packet The packet to read from.
result A reference to where the read number will be stored, if the return value is true.
Returns:
true if a u64 was read and stored in result; false if no such number could be read from the current position, because less than eight bytes remained to be read from packet.
Blinks:
E_API_INVALID_PACKET if packet is null or pointing at something that is detectably corrupt or not a packet.
Side Effects:
result is modified (if return true). The packetCursor() is advanced by either 8 (if return true) or 0 (if return false) bytes.
Since:
0.9.20

bool packetRead ( u8 packet,
u32 result,
int  code,
u32  maxLen 
)

Starting from the packetCursor() position, attempt to read a number into result, in the format specified by code, from packet.

See packetRead(u8 * packet, int &result, int code, u32 maxLen) for other details including the possible values of code and the meaning of maxLen.

Parameters:
packet The packet to read
result A reference to where the read number will be stored, if the return value is true.
code A code representing the format to read; see packetRead(u8 * packet, int &result, int code, u32 maxLen)
maxLen How many bytes to read at most; see packetRead(u8 * packet, int &result, int code, u32 maxLen)
Returns:
true if suitable number was read and stored in result; false if no such number can be read from the current position, either because an input unsuitable for code is seen first, or because the end of the packet is reached first.
Blinks:
See packetRead(u8 * packet, int &result, int code, u32 maxLen) for possible errors.
Side Effects:
The packetCursor() is advanced by however many bytes were successfully read, which will be a value between zero and the smaller of packetLength() and maxlen, inclusive. packetCursor() is left set equal to packetLength(), if the entire remainder of packet was read, or pointing at the first character of packet could not be interpreted as part of a number of type code, or at the next byte to be read after maxlen bytes have been read by this call.
Example:
    void myHandler(u8 * packet) {
      u32 num;
      if (!packetRead(packet,num,BIN))   // Can't really fail, the way it's set up..
        return false;                    // because there'll always be at least one legal byte to read..
      pprintf("received a packet beginning with %d in binary\n",num); 
    }
    void setup() {
      reflex('0',myHandler);  // Put same handler on both type 0
      reflex('1',myHandler);  // and type 1 packets.
    }
    ...

bool packetRead ( u8 packet,
int &  result,
int  code,
u32  maxLen 
)

Starting from packetCursor() of packet, consume no more than maxLen bytes to read an integer, in one of a variety of formats specified by code, and store the read value into result.

Parameters:
packet The packet to read.
result Where to store the read integer value
code What format number to read; one of: BYTE, BESHORT, or BELONG, or BIN, OCT, DEC, or HEX, or another number in the range 2..36 to read a number in that base.
maxLen Maximum number of bytes to read.
Returns:
true if number in the specified format was successfully read and stored in result; false otherwise.
Blinks:
E_API_INVALID_PACKET if packet is null or pointing at something that is detectably corrupt or not a packet.
Blinks:
E_API_FORMAT_ARG if code is not one of the valid values given above.
Side Effects:
If true is returned, the packetCursor() of packet is advanced by the number of bytes read, and result is overwritten with the read value. Note that if false is returned, the packetCursor() of packet may or may not have been advanced, depending on the reason for the failure.
Examples:
zformat1.cpp, and zformat2.cpp.

bool packetReadCheckByte ( u8 packet  ) 

Attempt to read a valid chack byte from the current position of packet.

Parameters:
packet The packet to read the check byte from.
Returns:
true if and only if packetReadLength() had been 1 (meaning we had been looking at the last byte of packet) and that byte was a valid check byte for the rest of packet, and returns false otherwise.
Blinks:
E_API_INVALID_PACKET if packet is null or pointing at something that is detectably corrupt or not a packet.
Side Effects:
None, if false is returned, otherwise the packetReadLength() of packet is decreased from 1 to 0, if true is returned.
Example:
    void myHandler(u8 * packet) {
      u32 val;
      if (!packetRead(packet,val,BYTE) || val != 'x') return; // Bail unless first byte is 'x'
      if (!packetRead(packet,val,DEC) || val >= 100) return;  // Bail unless then a decimal in 0..99
      if (!packetReadCheckByte(packet)) return;               // Bail unless then valid check byte
      pprintf("L received valid 'x%d' packet\n",val); // Announce success
    }
    void setup() {
      reflex('x',myHandler);         // Create an 'x' reflex
    }
    void loop() {
      pprint("x%d%\n",random(100));  // Broadcast x packets.  "%\n" appends the check byte!
      delay(1000);
    }

bool packetReadEOF ( u8 packet  ) 

Have we read to the end of packet?

Parameters:
packet The packet whose packetCursor() position to check
Returns:
true if and only if the packetReadLength() of packet is 0, meaning no more bytes can be read from packet.
Blinks:
E_API_INVALID_PACKET if packet is null or pointing at something that is detectably corrupt or not a packet.
Example:
    void myHandler(u8 * packet) {
      u32 ch;
      while (!packetReadEOF(packet)) {   // While there's still something in there..
        packetRead(packet,ch,BYTE);      // ..read another byte
        pprintf("got %c\n", ch);          // This can generate a lot of packets!
     }
    }
    void setup() {
      reflex('s',myHandler);  // 's' for 's'pam-generator..
    }
    ...

u8 packetReadLength ( const u8 packet  ) 

Access the 'read length' of packet.

The read length is the difference between the packetLength() and the packetCursor() of a given packet -- in other words, it is the number of further characters that may be read from packet.

Parameters:
packet The packet whose read length is needed
Returns:
from 0 to MAX_PACKET_LENGTH
Blinks:
E_API_INVALID_PACKET if packet is null or pointing at something that is detectably corrupt or not a packet.
Example:
    void pointlessDemo(u8 * packet) {
      if (packetReadLength(packet) > 0) {    // True if at least one byte can be read
        u8 ch;
        bool result = packetRead(packet,&ch,BYTE);   // So this must succeed
        API_ASSERT_TRUE(result);             // So the universe is insane if it doesn't
      }
    }

void packetReread ( u8 packet,
u32  newIndex 
)

Set the value of the 'read cursor' within packet to be newIndex, or to packetLength(const u8 *), whichever is smaller.

Parameters:
packet The packet whose read cursor to alter
newIndex The new position of packet's read cursor (default value: 0)
Blinks:
E_API_INVALID_PACKET if packet is null or pointing at something that is detectably corrupt or not a packet.
Side Effects:
packet's read cursor may be altered.
Example:
    void myHandler(u8 * packet) {
      u32 serialNumber;
      if (packetScanf(packet,"x%d:",&serialNumber) != 3) return; // Bail unless good start..

      u32 index = packetCursor(packet);              // Now remember where we are
      u32 val;
      if (packetScanf(packet,"0x%x\n", &val) != 4) { // Try for "0x" plus a hexadecimal..
        packetReread(packet,index);                  // But if that fails, back up..
        if (packetScanf(packet,"%d\n",&val) != 2)    // and try for a decimal instead
          return;                                    // And if that fails, punt
      }
      ..
    }

u8 packetSource ( const u8 packet  ) 

Access the source of packet.

The packet source is commonly, but not necessarily, the SFB face (NORTH, SOUTH, EAST, or WEST) that the packet arrived from.

Examples:
forward.cpp, hallucination.cpp, netled.cpp, pingpong.cpp, pingpong2.cpp, qled1.cpp, tee.cpp, zformat1.cpp, zformat2.cpp, and zformat3.cpp.

bool zpacketPrefix ( u8 packet,
const char *  to 
)

Determine if packet begins with the sequence of non-null bytes given by to.

Note that unlike 'packet reading' functions such as packetRead() or packetScanf, this function ignores the packetCursor() and always examines packet from the beginning.

Parameters:
packet The packet whose initial bytes are to be checked for a match against to.
to The zero-terminated string specifying a prefix to be sought in packet.
Returns:
true if packetLength(const u8 * packet) is >= strlen(to), and the first strlen(to) bytes of packet are identical to the corresponding bytes of to; and false otherwise.
Blinks:
E_API_INVALID_PACKET if packet is null or pointing at something that is detectably corrupt or not a packet.
Blinks:
E_API_NULL_POINTER if to is null.
Example:
    void myHandler(u8 * packet) {
      if (zpacketPrefix(packet,"foo")) {
        println("could be 'foo', 'foo bar', or 'food', but not 'fo', 'Foo', or ' foo'");
      }
    }


Generated on Fri Apr 22 06:56:07 2011 for SFB by doxygen 1.5.9