/**************************************************************************** * CODEC for the Real-time BBC Codec/Modem * **************************************************************************** * William L. Bahn * * Academy Center for Information Security * * Department of Computer Science * * United States Air Force Academy * * USAFA, CO 80840 * **************************************************************************** * FILE:............ codec.h * * DATE CREATED:.... 06 SEP 07 * * DATE MODIFIED:... 06 SEP 07 * **************************************************************************** * * REVISION HISTORY * **************************************************************************** * * DESCRIPTION * * The codec encodes and decodes messages to/from BBC-encoded packets. * **************************************************************************** */ #ifndef CODECdotH #define CODECdotH //------------------------------------------------------------------------ // REQUIRED INCLUDES //------------------------------------------------------------------------ #include "config.h" #include "source.h" #include "buffer.h" #include "sink.h" #include "dirtyd.h" #include "sha1.h" //------------------------------------------------------------------------ // STRUCTURE DECLARATIONS //------------------------------------------------------------------------ typedef struct CODEC CODEC; //------------------------------------------------------------------------ // STRUCTURE DEFINITIONS //------------------------------------------------------------------------ // NOTE: Normally the structure definition would be in the *.c file to make // the structure members inaccessible to outside functions except through // public function calls. But for the real-time code it has been decided // to make the structure members directly visible to the functions that // manipulate them. struct CODEC { // State information SHA1Context *state; // Pointer to single SHA1 structure SHA1Context *digest; // Pointer to single SHA1 structure // Decode buffer BYTE *msg; // Array containing the message bit contents (1 bit per byte) BYTE *checkbit; // Array indicating whether each bit is a message or check bit SHA1Context *hashstate; // Array of SHA1 structures }; //------------------------------------------------------------------------ // PUBLIC FUNCTION PROTOTYPES //------------------------------------------------------------------------ CODEC *CODEC_Del(CODEC *p); CODEC *CODEC_New(CONFIG *c, DWORD *errcode); void Encode(CONFIG *c, SOURCE *source, CODEC *codec, BUFFER *buffer); void Decode(CONFIG *c, BUFFER *buf, CODEC *codec, SINK *sink); /* DECODER * * The decoder decodes all eight of the packets that start with each of the * eight bits in the byte located at the present "read" location of the buffer. * * The value of the variable "originbit" determines which of the eight offsets * from the beginning of the byte the present packet starts at. The variable * "location" refers to the location of the bit in question relative to the * beginning of the packet. Therefore, relative to the beginning of the byte * where the packet starts, the location is simply "origin + location". This * combined location must then be turned into an index and and offset. The * "index" refers to which byte within the buffer contains the bit of interest * while the "offset" identifies the bit within that byte. The "index" value * must further account for the fact that the first byte in the packet is * located at the "read" point within the index and that the buffer is circular. * The "offset" value must be used to mask the byte being examined so that only * the bit of interest is considered. For speed purposes, this mask is provided * by a lookup table "bitmask". * * Taking all of this into account, the following steps will check if a * particular packet bit is set: * * index = {read + floor[(location + originbit)/8]} mod bufferlength * offset = (location + originbit) mod 8 * status = buffer[index] & bitmask[offset] * * Since the buffer length is exactly 2^n long, the residue of the index can * be taken by simply retaining only the lower n bits. Similarly, the residue * of the offset modulo-8 can be taken by only retaining the lower 3 bits. Both * of these can be done by performing a bitwise-AND with an appropriate mask. * Finally, the division of the effective location within the packet can be * performed by right-shifting the sum by 3 bits. Hence we have the following * equations: * * index = (read + ((location + originbit) >> 3)) & buffermask; * offset = (location + originbit) & 0x00000007; * status = buffer[index] & bitmask[offset] * * The most challenging part of the decoding algorithm is the backtracking that * must take place when the present partial message is finished, either because * it was found to be a dead end or because it resulted in an actual message. * The basic task is to traverse the decoding tree backwards until the last * partial message bit that was a zero is found. Then that bit is changed to a one * and decoding moves forward again. Two special cases have to be taken into * account. First, if there are no message bits that are zero, then the decoding * of that packet is finished. Second, checksum bits are always zero and the * decoder must skip over them without turning them to ones. * index 0123456789.... * check 1001001001.... * msg 0010110110.... * */ //------------------------------------------------------------------------ #endif