FSC-0014=0A=
A Bundle Proposal=0A=
=0A=
Wynn Wagner III=0A=
January, 1988=0A=
=0A=
=0A=
UPFRONT=0A=
-------=0A=
=0A=
What follows is a proposal for a new structure of message bundles that=0A=
are transmitted between Fidonet systems.=0A=
=0A=
Currently we deal with "packet version 2." This is a proposed format=0A=
for packet version three.=0A=
=0A=
The version number should be recognizable by TYPE-2 programs, but the=0A=
older programs will not be able to do anything more than report an=0A=
error. In other words, there is no direct upwards compatibility except=0A=
for the offset in the _BundleHeader (see below) of the TYPE-3 signal.=0A=
=0A=
Because of this, any conversion should be slow... possibly a year or =
more.=0A=
Interim systems would have to be able to pack and unpack both kinds=0A=
of bundles. It would be required for the packer to know whether its=0A=
target system knows about TYPE-3 bundles or not... either by some node=0A=
list flag or by using a control file.=0A=
=0A=
I think it is important that a new structure be seriously considered,=0A=
but it is also vital that we approach such a change with a mind to=0A=
keeping it an evolutionary process rather than an overnight revolution.=0A=
It is important that TYPE-2 systems be retired using attrition instead=0A=
of compulsion.=0A=
=0A=
This proposal is described in detail... possibly too much detail.=0A=
The design looks scarier than it really is. Code to process this=0A=
kind of a bundle is almost trivial.=0A=
=0A=
One design feature is that putting a message bundle together is =0A=
somewhat more involved than taking one apart. The theory is that we=0A=
will be getting more and more tiny installations operating as points.=0A=
Collecting and unpacking such things as echomail will be easier even=0A=
on small/slow computers. Heavy volume traffic with lots of packing=0A=
and unpacking is usually carried on by computers more capable of=0A=
heavy work. Please note that the added work on the shoulders of=0A=
the packer is almost microscopic, but it exists. This uneven =
distribution=0A=
of the work is intentional.=0A=
=0A=
=0A=
-------------------------------------------------------------------------=
-----=0A=
=0A=
PRELIMARIES: METHODS=0A=
--------------------=0A=
=0A=
Messages are transmitted in "bundles."=0A=
=0A=
A bundle is a sequence of "packets." Every bundle has at=0A=
least two packets: a header and a footer.=0A=
=0A=
This document describes the layout and use of those=0A=
packets as well as the general format of a bundle.=0A=
=0A=
=0A=
=0A=
=0A=
-------------------------------------------------------------------------=
-----=0A=
=0A=
PRELIMINARIES: DATA=0A=
-------------------=0A=
=0A=
=0A=
#define BUNDLEVER 3=0A=
#define EIDSIZ (sizeof(struct _Address)+sizeof(unsigned long))=0A=
=0A=
struct _Address {=0A=
unsigned int Zone;=0A=
unsigned int Net;=0A=
unsigned int Node;=0A=
unsigned int Point;=0A=
};=0A=
=0A=
DATA NOTES:=0A=
=0A=
"WORD" is a two byte unsigned integer with the most significant=0A=
byte first. This storage arrangement is backwards from=0A=
the way INTEL chips store numbers, but it is more in-line=0A=
with the way the rest of the universe does it. The=0A=
conversion for MsDOS and other INTEL programmers is quite=0A=
trivial.=0A=
=0A=
A routine called SWAP can be used, where...=0A=
=0A=
unsigned int pascal SWAP(unsigned int VALUE);=0A=
=0A=
Here's the code...=0A=
=0A=
SWAP Proc Near=0A=
mov bx, sp=0A=
mov ax, [bx+2]=0A=
xchg ah, al=0A=
ret 2=0A=
SWAP EndP=0A=
=0A=
"UNSIGNED LONG" is a four byte unsigned integer with the most=0A=
significant word first. Again, this storage arrangement=0A=
conflicts with the method used by INTEL, but the trans-=0A=
formation to "MSW first" is quite simple and it really=0A=
makes the non-MsDOS programmers feel more comfortable.=0A=
=0A=
"UNSIGNED CHAR" is an 8-bit datum that can have any value=0A=
between 0 and 0xff.=0A=
=0A=
CHARACTER ARRAYS are null-padded unless otherwise noted. There=0A=
is a difference between "null-terminated" (common to=0A=
C-language programming) and "null-padded" found here.=0A=
Unless there is a conflicting note, insignificant bytes=0A=
of a character array must be set to zero.=0A=
=0A=
UNUSED DATA are always set to zero.=0A=
=0A=
=0A=
=0A=
-------------------------------------------------------------------------=
-----=0A=
=0A=
BUNDLE HEADER=0A=
-------------=0A=
=0A=
struct _BundleHeader {=0A=
struct _Address B_Destination; /* Address of target system =
*/=0A=
struct _Address B_Origination; /* Address where bndl started =
*/=0A=
unsigned int B_Local1; /* Used by bundler, etc =
*/=0A=
unsigned int B_Version; /* Always 3 =
*/=0A=
unsigned long B_CreationTime; /* Unix-type stamp (1970-base) =
*/=0A=
unsigned int B_BundlerMajor; /* Major version of bundler =
*/=0A=
unsigned int B_BundlerMinor; /* Minor version of bundler =
*/=0A=
unsigned char B_Password[9]; /* NULL-padded array =
*/=0A=
unsigned char B_Local2; /* Local use only =
*/=0A=
unsigned char B_Product[4]; /* Meaningful to same product =
*/=0A=
unsigned char B_FTSC[4]; /* Reserved by FTSC =
*/=0A=
};=0A=
=0A=
BUNDLE HEADER NOTES:=0A=
=0A=
The offset of B_Version coincides with the location of the=0A=
`ver' field in type two bundle headers.=0A=
=0A=
The B_Local1 and B_Local2 fields have no meaning during the=0A=
actual transfer. It is to hold such information as COST=0A=
and/or BAUD rate of use to the sending system.=0A=
=0A=
B_Password is a NULL-padded field that can contain uppercase=0A=
alpha bytes or ASCII digits. It should not contain lowercase=0A=
characters, punctuation, control characters, etc. This is a=0A=
NULL-padded field... not just NULL-terminated. A maximum of=0A=
8 bytes are significant.=0A=
=0A=
Note that the BUNDLER is identified by product code. This =0A=
does NOT necessarily have anything to do with the software=0A=
that actually transmits the bundle. This structure deals=0A=
with message bundles, and the product identification shows=0A=
which computer program was responsible for that layer of=0A=
a netmail session. The software providing transportation=0A=
is more properly identified during a session-level negotiation =0A=
(eg WaZOO's YooHoo) or in a dynamically generated structure =0A=
(eg TeLink's block zero). TYPE-3 tries to keep the various=0A=
layers of the system separate and easily identifiable. This=0A=
document describes data, not the method by which they are=0A=
passed from one system to another.=0A=
=0A=
=0A=
BUNDLE BODY NOTES:=0A=
=0A=
The bundle header packet is followed by one or more of the=0A=
following packet types. Each of these packets begin with =0A=
two bytes that identify the packet version and the packet=0A=
type. In all cases, the version is three (0x03).=0A=
=0A=
Packet types include=0A=
=0A=
END_SIGNAL 0=0A=
AREA_HEADER 1=0A=
MESSAGE_HEADER 2=0A=
TEXT 3=0A=
ECHOMAIL_INFO 4=0A=
MISCINFO 128-256=0A=
=0A=
One message is built using at least two packets (MESSAGE_HEADER=0A=
and TEXT). Optionally, a message might also have ECHOMAIL_INFO=0A=
and MISCINFO packets. Packets associated with a message must=0A=
be bundled in numerical order (by packet type)... the header=0A=
comes first, followed by the text, possibly followed by echomail=0A=
information, and possibly ending with some miscellaneous =
packets.=0A=
=0A=
This arrangement of bundles allows the development of=0A=
state machine type programs which effect efficient message=0A=
processing even on slow or small computers. Here's a=0A=
quick coding example:=0A=
=0A=
for(;;)=0A=
switch(fgetc(BUNDLE)) {=0A=
default: printf("Not Type-3 message"); return -1;=0A=
case 3: switch(fgetc(BUNDLE)) {=0A=
case -1: printf("EOF?"); return -1;=0A=
case 0: printf("Done\n"); return 0;=0A=
case 1: GetMsgArea(); break;=0A=
case 2: GetMessage(); break;=0A=
default: printf("Pkt?"); break;=0A=
};=0A=
};=0A=
=0A=
NOTE: For those re-reading and spotting what looks=0A=
like a mistake... the `GetMessage()' routine=0A=
would also take care of TEXT and any ECHOMAIL =
=0A=
or MISCINFO packets.=0A=
=0A=
Also, for a little added robustness, the=0A=
default item that prints "Pkt?" should look=0A=
for a value of 0x03 (or and end of the file)=0A=
before returning to the processing loop.=0A=
=0A=
=0A=
=0A=
-------------------------------------------------------------------------=
-----=0A=
=0A=
BUNDLE FOOTER=0A=
-------------=0A=
=0A=
struct _BundleEnd {=0A=
unsigned char M_Version; /* Always 3 =
*/=0A=
unsigned char M_PacketType; /* Always 0 =
*/=0A=
};=0A=
=0A=
=0A=
BUNDLE END NOTES:=0A=
=0A=
All bundles end with this packet. It is not optional.=0A=
=0A=
=0A=
=0A=
-------------------------------------------------------------------------=
-----=0A=
=0A=
MESSAGE AREA=0A=
------------=0A=
=0A=
struct _AreaHeader {=0A=
unsigned char E_Version; /* Always 3 =
*/=0A=
unsigned char E_PacketType; /* Always 1 =
*/=0A=
unsigned byte E_NameLength; /* Actual bytes in E_Name =
*/=0A=
unsigned byte E_Name[1]; /* VARIABLE-length field =
*/=0A=
};=0A=
=0A=
AREA HEADER NOTES:=0A=
=0A=
The area header packet marks the start of a sequence of=0A=
messages destined for the same message area.=0A=
=0A=
Often E_Name will contain the name of an echomail area.=0A=
If the legnth and first byte of E_Name are zero, it means=0A=
that the following messages are inter-system traffic=0A=
(ie regular netmail).=0A=
=0A=
The maximum value for E_NameLength is 63.=0A=
=0A=
E_Name can contain uppercase characters, digits, and the=0A=
following punctuation: $ . - _ & # @ !=0A=
=0A=
Note that E_NameLength combined with E_Name make up what=0A=
is often considered a "Pascal style string." E_Name is=0A=
NOT a null-terminated array (aka "ASCIIZ").=0A=
=0A=
=0A=
=0A=
=0A=
=0A=
-------------------------------------------------------------------------=
-----=0A=
=0A=
MESSAGE HEADER=0A=
--------------=0A=
=0A=
struct _MessageHeader {=0A=
unsigned char M_Version; /* Always 3 =
*/=0A=
unsigned char M_PacketType; /* Always 2 =
*/=0A=
struct _Address M_Destination; /* FINAL Destination =
*/=0A=
struct _Address M_Origination; /* Where message was entered =
*/=0A=
unsigned long M_CreationTime; /* Unix-type stamp (1970-base) =
*/=0A=
unsigned int M_Attributes; /* Standard Fidonet bitweights =
*/=0A=
unsigned char M_FromLength; /* Number of bytes in FROM =
*/=0A=
unsigned char M_ToLength; /* Number of bytes in TO =
*/=0A=
unsigned char M_SubjectLength; /* Number of bytes in SUBJECT =
*/=0A=
};=0A=
=0A=
=0A=
MESSAGE HEADER NOTES:=0A=
=0A=
Every message begins with a message header packet. This=0A=
structure is created by the system where the message=0A=
originated. If there are any intermediate stops before=0A=
it reaches its destination, it is the responsibility of=0A=
intermediate systems to maintain all of this information=0A=
without any modification.=0A=
=0A=
Following this header come three char-type data: FROM, TO,=0A=
and SUBJECT. Using the final three fields of the header,=0A=
a program can quickly read and process/store the the message.=0A=
=0A=
None of the character items is null-terminated. Their=0A=
lengths are determined by values in the message header.=0A=
=0A=
=0A=
=0A=
=0A=
=0A=
-------------------------------------------------------------------------=
-----=0A=
=0A=
MESSAGE TEXT/BODY=0A=
-----------------=0A=
=0A=
struct _Text {=0A=
unsigned char T_Version; /* Always 3 =
*/=0A=
unsigned char T_PacketType; /* Always 3 =
*/=0A=
unsigned int T_ByteCount; /* Number of bytes ( <0x1000) =
*/=0A=
unsigned int T_Data[1]; /* VARIABLE-length field =
*/=0A=
};=0A=
=0A=
TEXT NOTES:=0A=
=0A=
The body of a message is contained in one or more _Text packets.=0A=
=0A=
No _Text packet is ever more than 1000H bytes long. That's=0A=
4096 bytes to the terminally base-10 folks. Of course there=0A=
can be an infinite number of text packets, but you are=0A=
absolutely positively guaranteed that with the TYPE-3 method,=0A=
you will never need a buffer larger than 1000H.=0A=
=0A=
In addition to ASCII values 20h through 7Eh (inclusive),=0A=
the following control codes are legal for TEXT data.=0A=
Note that <cr> and <softCR> are NOT in this list.=0A=
=0A=
<stx> 02H ... material from here to next <lf> is=0A=
a quote from the parent message=0A=
<lf> 0Ah ... forced <cr/lf>=0A=
<dle> 10h ... replicate=0A=
=0A=
Other control characters and values 7fH and above are=0A=
symptoms of a damaged message.=0A=
=0A=
REPLICATE is a three byte sequence: <dle><value><length>.=0A=
For example, if a message contains the bytes 10h, 20h, 09h ...=0A=
it would mean that message display programs should replicate=0A=
the <space> character nine times. =0A=
=0A=
There is no minimum or maximum line length. If there is no=0A=
<lf> before the display program needs one, it is the display=0A=
program's responsibility to provide the needed "line wrap."=0A=
=0A=
One "line" can cross from one _Text packet to another.=0A=
=0A=
=0A=
=0A=
=0A=
=0A=
-------------------------------------------------------------------------=
-----=0A=
=0A=
ECHOMAIL=0A=
--------=0A=
=0A=
struct _EchomailInfo {=0A=
unsigned char EI_Version; /* Always 3 =
*/=0A=
unsigned char EI_PacketType /* Always 4 =
*/=0A=
unsigned char EI_Parent[EIDSIZ];/* "up" message thread =
*/=0A=
unsigned char EI_Child[EIDSIZ]; /* "down" message thread =
*/=0A=
unsigned int EI_SeenbyCount; /* Number of SEENBY items =
*/=0A=
struct _Address EI_Seenby[1]; /* VARIABLE-length field =
*/=0A=
};=0A=
=0A=
=0A=
ECHOMAIL INFO NOTES:=0A=
=0A=
The EI_Parent and EI_Child fields contain some kind of=0A=
identification of the parent and child messages. The size=0A=
of the fields corresponds to the size of an _Address=0A=
structure plus the size of a Unix-type time stamp.=0A=
=0A=
=0A=
=0A=
-------------------------------------------------------------------------=
-----=0A=
=0A=
A KLUDGE, BY ANY OTHER NAME...=0A=
------------------------------=0A=
=0A=
struct _MiscInfo {=0A=
unsigned char MI_Version; /* Always 3 =
*/=0A=
unsigned char MI_PacketType; /* 0x80-0xff, assigned by FTSC =
*/=0A=
unsigned char MI_ByteCount; /* Size of miscinfo data =
*/=0A=
unsigned char MI_WhoKnows; /* Miscellaneous stuff =
*/=0A=
};=0A=
=0A=
=0A=
MISCELLANEOUS INFO NOTES:=0A=
=0A=
This is the catch-all packet type that replaces "The Dreaded=0A=
IFNA Kludge."=0A=
=0A=
If present, they are the last packets associated with a=0A=
message. _MiscInfo items are bound to a message, and it=0A=
is the responsibility of any packer to maintain any =0A=
_MiscInfo packets exactly as they arrived on any message=0A=
that will be retransmitted (ie netmail and echomail).=0A=
=0A=
Values above 0xf0 have a special meaning. They are =0A=
reserved for the severe case that FTSC needs to make some=0A=
kind of change that isn't backwards compatible. In most=0A=
cases, unrecognized _MiscInfo packets should be preserved=0A=
but otherwise ignored. If the packet type is 0xf0 through=0A=
0xff, it should be considered an error condition not to=0A=
understand the packet.=0A=
=0A=
=0A=
###=0A=
=0A=