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 and are NOT in this list.=0A= =0A= 02H ... material from here to next is=0A= a quote from the parent message=0A= 0Ah ... forced =0A= 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: .=0A= For example, if a message contains the bytes 10h, 20h, 09h ...=0A= it would mean that message display programs should replicate=0A= the character nine times. =0A= =0A= There is no minimum or maximum line length. If there is no=0A= 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=