textfiles/bbs/FIDONET/JENNINGS/STANDARDS/fidomail.doc.txt

1519 lines
49 KiB
Plaintext
Raw Normal View History

2021-04-15 11:31:59 -07:00
Fidonet Electronic Mail Protocol 20 Oct 84 Page 1
Tom Jennings
2269 Market Street #118
San Francisco CA 94114
FidoNet Node #1
415/864-1418
INTENT
This document is an attempt to describe and define
the packet protocol used to support electronic mail under
the Fido/FidoNet system.
It will not describe or define Fido/Fidonet software
operation, nor even describe what the system does; for that,
I refer you to the following Fido manuals:
Fido's Installation Manual (INSTALL.DOC)
Fido's Operating Manual (FIDO.DOC)
Fido's FidoNet Manual (FIDONET.DOC)
Only the lower layers of the protocol will be
discussed here; routing, forwarding, dialing algorithms and
such will not be covered. These are mentioned, albeit
briefly, in Fido's FidoNet Manual.
BACKGROUND
FidoNet was designed to be more or less portable
within the existing "public domain" software base, ie. any
system that can support binary transfers via XMODEM or it's
variants is in theory capable of supporting FidoNet. This
does not mean to imply that the current Fido/FidoNet
software will be/can be transported to machines not
currently supported; it means that no designed in
limitations were intended.
This document merely covers the algorithms used, and
the problems encountered, in the automatic transfer of
packets and files used by the MSDOS Fido/FidoNet system.
DESCRIPTION
FidoNet is a true electronic mail system supported
by the Fido Bulletin Board System software, under MSDOS
version 2. It's function is to transfer textual messages,
and binary files, between physically seperate computers on
an automatic, unattended basis.
BASIC ASSUMPTIONS
The basic unit of data in FidoNet, like most MSDOS
and CPM software, is the byte, which here means 8 bits. All
data transfers assume the availability of an 8 bit byte
capable channel; 7 bit ASCII is not adequate. Parity, if
Fidonet Electronic Mail Protocol 20 Oct 84 Page 2
used, must be transparent to the software.
FidoNet is transaction oriented; a channel
(connection) is made, data transferred, the channel closed.
In all existing cases, this means a typical modem/phone line
connection; dial, connect, transfer, disconnect, though
anything that might be considered a "channel" will work.
The most basic design criteria for FidoNet is
extremely short channel connect times, since the usual
channel is a telephone line, where costs are accumulated on
a per minute basis. Lowest possible costs is the single most
important issue here. For this reason, all packets are
preassembled; no processing at all is done at packet
transfer time.
Due to the lack of real time operating systems,
FidoNet runs on an alternating basis with Fido. While Fido
is running, users enter messages, attach files and the like,
to be later processed by FidoNet. When FidoNet gains control
(at a predetermined time of day) it packetizes outgoing
messages, then makes attempts to send these packets, and may
receive packets from other nodes, all asynchronouously. When
FidoNet's time slot is over, it deletes any un-sent packets,
unpacks any packets that were received, and then passes
control back to Fido. Note that incoming packets are not
examined in any way until the FidoNet time slot is over.
A basic concept in FidoNet is the "node". A node is
any computer capable of sending or receiving FidoNet mail
packets. All discussions of packet transfers here will
assume point to point transfers.
As background information, it should be noted that
routing, forwarding, cost accounting, etc is done at a much
higher layer; routing, for instance is done even before
packets are created, and determines the destination node. It
has no effect on packet transfer.
SOFTWARE ASSUMPTIONS
Fido/FidoNet is written in 'C' (Lattice flavor) and
makes use (of course) of C style structures and strings.
Luckily, these are quite simple. Here are the following
basic components used throughout FidoNet:
CHARACTERS:
An 8 bit byte. The usual micro type "character"; all
8 bits may be signifigant. Usually 128ASCII.
STRING:
A one dimension array of 8 bit characters,
terminated by a null. (hex 0) Some are of a fixed length; in
this case, signifigant text is left justified, followed by
the null, and the rest of the string is indeterminate. In
practice, FidoNet strings vary from very few characters up
to 4000 characters or so.
Fidonet Electronic Mail Protocol 20 Oct 84 Page 3
INTEGERS:
All integer variables are 16 bits ('C' shorts)
unsigned, and are in Intel (big endian) format; least byte
first in the byte stream.
LONGS:
A long integer is 32 bits, in Intel format.
WHAT A PACKET IS
A packet is a file that consists of a header, a
variable amount of variable size messages, and a trailer.
Each message within a packet has a header, and a single
string of plain text.
+---------------+
| |
| | Header
| |
+---------------+
| | Message #1
+---------------+
| |
/ /
/ /
| |
+---------------+
| | Message #N
+---------------+
| | Trailer
+---------------+
The header and trailer are of fixed length. All of
the messages are variable length, but have a fixed number of
fields within them.
Packets must be treated as a byte stream; for many
of the components, "type" flags determine the format of
upcoming data, therefore it is difficult to "read ahead",
except for buffering purposes.
THE HEADER:
The header is a fixed length structure, and contains
the originating and destination nodes, the date the packet
was made, a version number, and some extra space for future
expansion.
Foolishly, there is no "type" identifier in the
packet header.
A PACKET MESSAGE:
Each message contains an interger "type", followed
by the message fields. These are: attribute, originating
Fidonet Electronic Mail Protocol 20 Oct 84 Page 4
node, destination node, two zeros, cost, date string, "to"
string, "from" string, "Subject" string, followed by the
text string.
The type, attribute, orig and dest node numbers, the
two zeros and cost are all integers. The other are serial
byte streams, strings, of variable length.
INPORTANT NOTE:
Due to extreme shortsightedness in the original
packet design, the message type 1 did not include the
originating and destination node numbers; FidoNet inserted
the node numbers found in the packet header when the message
was unpacked and stored in the system.
Routing meant that messages for many different nodes
were packed into a single packet; needless to say this means
that the node numbers may not be the same for each message,
as was the previous assumtion.
A message type 2 (the one described above) was added
to accomodate the "extra" information. Starting in version
10, FidoNet will no longer create message type 1, though it
will continue to receive them. Other implementations may
ignore message type 1, and assume that all are message type
2.
THE TRAILER:
The trailer consists of a single integer 0. This can
be thought of as a message type 0. This ends the packet; any
data following it (as when XMODEM rounds the packet up to
the next highest 128 bytes) should be ignored.
SYSTEM ASSUMPTIONS
Fido and FidoNet were designed using some basic
software building block concepts, admittedly stolen from
Ward Christensen's MODEM program.
XMODEM with CRC error checking is used for the basic
mail packet transfer. No further discussion will be made as
to XMODEM implementation nor operation. Please refer to
other documents.
MODEM7, or more accurately, TELINK, protocol is used
to transfer any files "attached" after the message packet.
TELINK is identical to MODEM7, with the addition of an extra
data block, that passes MSDOS dependent file information
(time, date, exact file size) before the first data block.
FidoNet is still MODEM7 capable; all that is necessary is to
NAK the extra block, whose header character is ASCII SYN
instead of SOH when receiving from a TELINK based FidoNet.
For sending to TELINK based receiving FidoNets it is not
necessary to send this extra block. This protocol is also
Fidonet Electronic Mail Protocol 20 Oct 84 Page 5
described elsewhere.
FidoNet assumes the presence of a clock of some
sort, for failsafe monitoring of packet transfers, and for
accounting purposes, to monitor actual connect times.
Accounting is outside the scope of this document.
A clock timer, preferably interrupt driven, is
needed to monitor the initial connection process, though may
be done using polled counters, if they are "calibrated".
This is fairly important; it prevents excessive connect
times if either the sender or receiver fails at any point.
There are two basic subroutines used in the Fido
implementation of FidoNet. While these are very low level
hardware dependent routines, they are very important in
concept.
DELAY ( N )
Delay for N centiseconds. This is just a time delay,
or time waster routine. It is used for generating time
delays for accomodating the telephone companies equipment.
MODOUT ( CHARACTER )
Send a character to the modem. This is shown for
illustration purposes; it is used in the diagrams to follow.
MODIN ( N )
Receive a character from the mode, but wait no
longer than N centiseconds. If a character is received, it
is returned; if it times out, -1 is returned. Since
characters are 8 bits, -1 (16 bits) indicates that no valid
character was received. This is a very basic, very important
function, upon which all of FidoNet is based.
The centisecond timer does not need to be accurate.
10% or less error is ideal, 20% is acceptable, and Fidonet
will usually still operate at up to 100% error. However,
repeatability will suffer, and sensitivity to the "length"
of a telephone connection will increase rapidly above 25%
error.
This is implemented on MSDOS as an interrupt driver
timer; a polled timing loop is adequate if adjusted to match
the processor speed.
Fidonet Electronic Mail Protocol 20 Oct 84 Page 6
PACKET TRANSFERS
Packet transfers will be described in two ways here;
first, a prose description, lacking exact details, and a
diagram with tables, with exact timing relationships and
values.
A FidoNet session consists of the following:
- Building routing tables
- Building list of active nodes
- Creating packets
- Compiling Messages
- Compiling list of attached files
- Sending/receiving Packets
- Deleteing outgoing packets, marking sent messages
- Unpacking incoming packets
- Return control to Fido
Only the creating of packets and attached file
lists, their transmission and reception, and unpacking is
covered here. The other steps are Fido dependent, and will
vary from implementation to implementation.
CREATING PACKETS:
FidoNet makes a number of passes through all of the
messages in the system. The first pass is merely to
determine which nodes have messages destined to them. Each
node is marked in a table, for later use in making packets
and dialing.
Additional passes are made, one for each node there
is mail to. A packet file is created on disk, using the
destination node number to create a unique filename (44.out
for a packet to node 44, etc), and the packet header is
written out.
When a message to this node is found, the message is
written out to the packet file. (The messages as stored in
Fido are described later in detail)
After the last message is written to the packet, the
trailer is written out, the file closed.
This process is repeated for all nodes that have
mail to be sent.
Fidonet Electronic Mail Protocol 20 Oct 84 Page 7
SENDING PACKETS:
RECEIVING PACKETS:
FidoNet alternates sending and receiving packets for
most of the time slot. When it is not actually sending (or
attempting to send) a packet, it is waiting for one.
If there are no incoming calls, FidoNet makes
outgoing calls at a random one or two minute interval. A
node is chosen to call from the table compiled while making
packets. A node is picked sequentially from this table,
trying each one in sucession. When the end of the table is
reached, it starts over at the beginning.
When it is time to place a call, the next node is
chosen from the table, the telephone number is dialed. If no
connection is made, FidoNet goes back into receive mode.
If a connection is made, CRs are sent, to determine
the baud rate. When the called system determines the baud
rate, it sends the "signon" message telling human callers it
is not available. This message is detected by the caller,
and terminates the baud detection. If baud is not detected
in 8 seconds, the caller disconnects.
The sender then waits for the line to clear (the
signon message to stop), then sends a character designated
as "TSYNC". This tells the receiver that it is a FidoNet
node calling, instead of a human caller. There is a 60
second limit placed on the TSYNC sequence. The receiver then
goes into XMODEM file receive, with a unique name for the
incoming packet. (0.in, 1.in ...)
After sending TSYNC, the sender transmits the packet
(N.OUT) using normal XMODEM protocol.
After the packet is sent, the receiver goes
immediately into MODEM7 mode, to receive any attached files.
If there are no attached files, the sender sends an
EOT, which when received by the receiver in MODEM7, tells it
"no more files". If there are attached files, the sender
sends all of the files in the attached file list, using
MODEM7.
After either sending the attached files, or after
sending the EOT meaning no attached files, the sender delays
five seconds, then disconnects. After receiving the last
attached file (or the EOT) the receiver delays two seconds
and disconnects. The delay is to accomodate the telephone
systems peculiarity of keeping connect information on a
seperate, faster, channel that the data itself; without the
delay, it is possible for the "disconnect" to get there
before the character does.
If the packet was sent sucessfully, the sender
deletes the outgoing packet, the attached file list, and
Fidonet Electronic Mail Protocol 20 Oct 84 Page 8
marks the node table as "sucessful", and then returns to the
receive and wait mode.
UNPACKING PACKETS:
When FidoNet mail time is over, any unsent outgoing
packets are deleted, and all messages that were sent
sucessfully are marked as SENT.
Each incoming packet (0.in, 1.in ...) is unpacked
and deleted. First, the destination node number is compared
to the nodes actual number. If it does not match (this
packet not really meant for this node) the packet is deleted
without further unpacking. If it matches, the messages are
unpacked and placed in the message area.
The packet is read as a byte stream, and interpreted
as read. When a message type is found, FidoNet assembles the
message as it goes.
Note that it is possible to receive part of a
packet; Fidonet will unpack all complete messages and store
them in the message area. It may find an error, such as an
incomplete packet. This is not a necessary feature; since
the packet was aborted, it will be sent again the next
night.
Fidonet Electronic Mail Protocol 20 Oct 84 Page 9
FIDONET DIALING AND PACKET TRANSFER
This is the final, detailed, description of the
actual packet transfer. Some shorthand notation will be used
here; "clock" means a general purpose timer for monitoring
elapsed time, and is set and read during many parts of the
packet protocol. The two subroutines described above are
also used through out.
The descriptions her are in a C like "pseudo code",
for simplicity. Function or subroutine calls are shown as:
function(parameter);
Where function() is the subroutine, and "parameter"
is a parameter passed to the function. Parameters here may
be numeric values or strings, which can be determined from
context. Functions without parameters are shown as
function(). Functions may return a value, so that:
x= function()
Sets variable X to the value returned by function().
IMPORTANT NOTE:
Ther is one extremely important construct that does
not, and cannot show up in these diagrams. This is a
mechanism to monitor Carrier Detect on the modem, and return
directly to a high level subroutine for error handling. This
is important due to the huge number of place where carrier
loss would have to be checked for, with the corresponding
high number of error return checks.
This can be implemented with a C like "set_jmp",
which stores the stack pointer and a return address, and
jumps to the return address if carrier is lost.
Also, in the Fido implementation, this error exit is
taken when the clock goes over the set limit. This frees the
high level code from having to watch the clock constantly.
The actual high level packet receive and send C
source is included at the end of this document to hopefully
make this a bit clearer.
All mnemonics are standard ASCII control characters,
with the exception of "TSYNC", described below.
Control Character Definitions
Char Hex Dec
---- --- ---
CR 0d 13
EOT 04 4
TSYNC ae 174
Fidonet Electronic Mail Protocol 20 Oct 84 Page 10
PACKET TRANSMISSION:
send_packet:
Attempt to place the call. If no connection, just return,
where FidoNet will wait for an incoming call, or delay one
or two minutes to place the next outgoing call.
set baud rate from node list
dial phone number,
if no connection, return
A connection has been made. Determine the baud rate first.
This "whacks return" up to eight times; if no message
appears from whacking, it stops and calls it an error. The
"double whack" (sic) seems to work better than a single CR.
When the receiver determines the baud rate, it sends 4 CRs,
and the signon message, which also contains CRs. The sender
notices this and stops sending its CRs.
for (i= 1 to 8) {
send CR, delay(20), send CR;
if (modin(100) == CR) break out of loop;
}
if (no CR received above) {
mark table as one "connect",
disconnect,
return.
}
Baud rate is now detected. Set the failsafe timer, wait
until the line clears (the signon message stops coming),
then send TSYNC. If one minute elapses, disconnect and
return.
print ("Connected");
set clock to zero;
while (clock is less than one minute) {
if (modin(50) == -1) break out of loop;
}
if clock == one minute {
disconnect,
return.
}
send (TSYNC);
disable clock;
print ("Sent TSYNC");
Presumably, all connected now. Start sending the packet via
XMODEM. XMODEM will timeout after so many tries, so that
this will not hang if the other end fails or is not a
FidoNet.
Fidonet Electronic Mail Protocol 20 Oct 84 Page 11
print "Sending Packet"
xmodem send (packet);
Packet transmission complete. Mark the in memory table as
"succesful". If there are attached files, send them now,
otherwise just send an EOT.
success= 1;
if (attached files)
modem7 send attached files
else send EOT.
All sent, delay 5 seconds to let things settle down.
delay(500)
disconnect,
return.
Fidonet Electronic Mail Protocol 20 Oct 84 Page 12
PACKET RECEPTION:
Carrier was detected while waiting to place a call or
waiting for an incoming call. Determine baud rate first,
display the signon message, then wait for TSYNC. There is a
one minute limit waiting for TSYNC. Note that connect()
watches the clock while waiting for CRs, and will take a
fatal error abort if it goes over the set limit. This
example therefore assumes that it will not timeout.
receive_packet:
reset clock,
connect() determine baud rate
print to modem:
"FidoNet Version x.x
FidoNet Node #N
Processing mail Only"
while (clock less than one minute) {
if modin(100) == TSYNC break out of loop;
}
if (over one minute) {
disconnect,
return;
}
All connected, received TSYNC. Wait for the incoming packet.
Each incoming packet is named sequentially, starting at 0;
0.in, 1.in, 2.in, etc. If no packet was received, quite now;
no sense in trying to get attached files if no packet
received.
xmodem receive packet
if no files received {
disconnect,
return.
}
Since it may have taken a few seconds to close up and write
out the packet file, the sender may have sent extra EOTs
from the end of the XMODEM packet transfer. Delay a bit, and
flush out the modem.
delay(200),
flush modem,
Now just go right into MODEM7 receive, for any attached
files. If there are none, the sender will send us an EOT,
which tells MODEM7 there are no more files. It can also just
hang up at this point, since the packet has already been
received. After the last, if any, file(s) received, delay 2
seconds and disconnect.
receive modem7 *.*
Fidonet Electronic Mail Protocol 20 Oct 84 Page 13
delay(200),
disconnect,
return.
Fidonet Electronic Mail Protocol 20 Oct 84 Page 14
IMPLEMENTATION NOTES:
These are some suggestions on implementing FidoNet
on all systems. They are merely suggestions; obviously you
can do what you want.
LOW LEVEL FUNCTIONS:
As mentioned before, there are some low level
functions that at least some of which are probably
universal. The ideas below may make it easier to implement a
"bullet proof" FidoNet.
ELAPSED TIME CLOCK:
This is a necessity, in one form or another. It's
accuracy does not need to be high. In Fido, it is
implemented as a timer tick interrupt, that increments in
memory variables: 'millisecs', 'seconds', 'minutes', and a
function to clear the clock, ie. set the above counters to
zero. (millisec is almost never actuall milliseconds; on the
IBM PC, for instance, the clock tick is at 55.55 mS; 55 is
added to 'millisec' every clock tick.)
There is an additional variable called 'limit', that
is the time limit to enforce for a particular routine.
Setting it to zero effectively disables the limit.
Thirdly, there is a function called limitchk(), that
does two things:
1. Watches the set time limit vs. the minute counter
2. Watches the carrier detect line from the modem
If either one of these events happens, it takes the
fatal error trap, and returns directly, instead of returning
normally.
limitchk() {
if (limit > 0) {
if (minutes >= limit) frc_abort();
}
if ! dsr()) frc_abort();
}
frc_abort() is the fatal error jump, back to the
caller directly. dsr() is a function that returns false (0)
if carrier is lost. If no fatal errors, limitchk() just
returns.
MODIN(N)
MODOUT()
Fidonet Electronic Mail Protocol 20 Oct 84 Page 15
These two are the lowest level character IO in Fido.
modin(N) returns either a character from the modem, or -1
(TIMEOUT) if no character was available within N
centiseconds. This avoids hanging forever waiting for a
character that may never come.
modout() merely sends a character to the modem.
Both of these functions check for errors by calling
limitchk() while waiting for input or output ready.
modin(n)
int n;
{
millisec= 0L;
while (millisec < (10 * n) ) {
if (character ready) return(modem char);
limitchk();
}
return(-1);
}
modout(c)
char c;
{
while (output not ready) {
limitchk();
}
send char to modem
}
Fidonet Electronic Mail Protocol 20 Oct 84 Page 16
MESSAGES
While the message format is very Fido dependent, it
may be illustrative to show the correspondence between a
"normal" Fido message and one that has been installed in a
packet.
This is the format of a Fido message, as contained
in any Fido Message Area.
/* Message header structure. The message text is just a long
string. */
struct _msg {
char from[36]; /* who from, */
char to[36]; /* who to, */
char subj[72]; /* message subject, */
char date[20]; /* creation date, */
int times; /* number of times read, */
int dest; /* destination node, */
int orig; /* originating node */
int cost; /* actual cost of msg */
int caca[6]; /* extra space, */
unsigned reply; /* thread to previous */
int attr; /* message type, */
int up; /* thread to next */
};
/* The message text starts at the byte following the end
of the structure, and is terminated by a single null. */
/* Bit values for msg.attr */
#define MSGPRIVATE 1 /* private message, */
#define MSGREAD 4 /* read by addressee */
#define MSGSENT 8 /* sent OK (remote) */
#define MSGFILE 16 /* file attached to msg */
#define MSGFWD 32 /* being forwarded */
#define MSGORPHAN 64 /* unknown dest node */
#define MSGKILL 128 /* kill after mailing */
A Fido message is 191 bytes minimum; 190 bytes of
header, above, and a variable amount of message text, null
terminated. A fairly large klunky thing to pass around. When
compacted into a packet, it is much smaller. As an example,
assume the following message:
From: Tom Jennings On Fido 1
To: John Madill On Fido 2
Subject: Test message
This is text in the test message.
A hex dump of this test message follows. Note that
the null terminated strings are followed by garbage; please
ignore it.
Fidonet Electronic Mail Protocol 20 Oct 84 Page 17
54 6F 6D 20 4A 65 6E 6E-69 6E 67 73 00 00 8E 36 Tom Jennings...6
00 00 00 FE FF 06 00 00-00 00 96 36 31 00 F3 21 ...~.......61.s!
0A 00 00 00 4A 6F 68 6E-20 4D 61 64 69 6C 6C 00 ....John Madill.
86 99 F8 27 86 99 02 28-00 00 91 36 57 61 69 74 ..x'...(...6Wait
20 2E A0 99 AE 16 68 21-74 65 73 74 20 6D 65 73 . ...h!test mes
73 61 67 65 00 00 65 00-FF 00 FC FF 00 00 B8 99 sage..e...|...8.
40 00 AF 06 AF 06 65 06-40 00 65 00 65 00 FC FF @././.e.@.e.e.|.
00 00 AF 06 0D 06 40 00-65 00 FF 00 FC FF 00 00 ../...@.e...|...
DA 99 65 00 AF 06 7E 60-1D 1A 83 F2 99 36 BC 27 Z.e./.~`...r.6<'
32 33 20 4F 63 74 20 38-34 20 20 31 36 3A 31 39 23 Oct 84 16:19
3A 34 38 00 01 00 02 00-01 00 1B 00 00 00 00 00 :48.............
00 00 00 00 00 00 00 00-00 00 81 00 00 00 20 20 ..............
54 68 69 73 20 69 73 20-74 65 78 74 20 69 6E 20 This is text in
74 68 65 20 74 65 73 74-20 6D 65 73 73 61 67 65 the test message
2E 0D 0A 0D 0A 00 ......
When the message is packetized, it becomes much
smaller; an entire packet, header, the above message and
trailer, is only 164 bytes. The extra space and most of the
Fido dependent items are removed.
01 00 02 00 C0 07 09 00-02 00 10 00 19 00 0E 00 ....@...........
00 00 01 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
00 00 00 00 00 00 00 00-00 00 01 00 01 00 1B 00 ................
32 33 20 4F 63 74 20 38-34 20 20 31 36 3A 31 39 23 Oct 84 16:19
3A 34 38 00 4A 6F 68 6E-20 4D 61 64 69 6C 6C 00 :48.John Madill.
54 6F 6D 20 4A 65 6E 6E-69 6E 67 73 00 74 65 73 Tom Jennings.tes
74 20 6D 65 73 73 61 67-65 00 20 20 54 68 69 73 t message. This
20 69 73 20 74 65 78 74-20 69 6E 20 74 68 65 20 is text in the
74 65 73 74 20 6D 65 73-73 61 67 65 2E 0D 0A 0D test message....
0A 00 00 00 ....
The packet header format is as follows. It is
possible to follow, and hand disassemble, the message
packet.
struct _hdr {
int orig; /* originating Node # */
int dest; /* destination node */
int year,month,day,hour,minute,second;
int rate; /* baud rate */
int ver; /* packet version */
int extra[19];
} pkthdr;
Fidonet Electronic Mail Protocol 20 Oct 84 Page 18
#include <stdio.h>
#include <ctype.h>
#include <bbs.h>
#include <xfbuf.h>
#include <ascii.h>
#include <xtelink.h>
#define TSYNC 0xae
extern char ver[];
extern unsigned crcmode; /* 1 if CRC mode, */
extern unsigned filemode; /* transfer type; XMODEM, MODEM7, TELINK */
/* Statistics on file transmission. */
extern unsigned totl_files; /* total files sent/rec'd */
extern unsigned totl_failures; /* how many failed, */
extern unsigned totl_errors; /* error count, soft errors incl */
extern unsigned totl_blocks; /* number blocks sent, */
extern int minutes,seconds;
extern int pktnum; /* incoming packet number */
extern struct _route route[ROUTE_SIZE]; /* routing table */
extern int maxnode; /* number of nodes in route table */
extern struct _sched sched[SCHEDS]; /* scheduled events */
extern char tag; /* handy local copy of the tag */
extern int event; /* handy local copy of the current event */
extern struct _nmap nmap[MAXNODES]; /* working node table */
extern int nn; /* current node, */
extern int nodetotal; /* number of nodes in the table */
extern struct _pkthdr pkthdr; /* FidoNet packet header */
extern struct _mail mail; /* MAIL.SYS */
extern struct _node node; /* in memory node descriptor */
extern struct _sys sys;
extern char *_txbuf; /* message display buff, ASCII upload */
extern int sysfiles; /* total system files, */
extern int overwrite; /* 1 == allow overwriting files */
extern int xferdisp; /* 1 == display up/dn load status */
extern int rate; /* baud rate */
extern int cd_flag;
extern int limit;
/* Carrier detected. Determine the baud rate, display a message to
tell humans what were doing, then get in sync with the sender. Once
in sync, receive the mail packet. */
rcv_mail() {
Fidonet Electronic Mail Protocol 20 Oct 84 Page 19
int i,n;
char pktname[80];
int msg_pkts,msg_blocks;
gtod(pktname);
lprintf("Call in @ %s\r\n",pktname); /* log the call, */
cprintf(" * Incoming Call\r\n");
clr_clk(); /* reset the clock, */
limit= 1; /* limit to connect, */
cd_flag= 0; /* watch Carrier Detect */
/* We get an abort if: timeout, no sync (human caller), actual file transfer
error, or packet received and sender hangs up. Totl_files is 0 if no
packets transferred. */
totl_blocks= 0;
totl_files= 0;
msg_pkts= 0;
msg_blocks= 0;
set_abort(0); /* trap carrier loss here, */
if (was_abort()) {
if (msg_pkts == 0) {
cprintf(" Receiving Mail Packet Aborted\r\n");
lprintf("\r\n*Aborted\r\n");
} else {
cprintf(" * Received %u packets\r\n",msg_pkts);
lprintf(" %u pkts %u blks OK\r\n",msg_pkts,msg_blocks);
if (totl_files > 0) {
cprintf(" Received %u files\r\n",totl_files);
lprintf("Recv'd Files\r\n");
}
}
cd_flag= 0; /* real CD, */
if (dsr()) discon(); /* hang up, delay for telco */
else delay(200); /* delay for telco */
return(msg_pkts);
}
/* The sender whacks CR until it gets a CR back. It then waits for the
message to stop, sends a TSYNC, and starts the transfer. */
/* -------------------- One Minute to Complete This ---------------------- */
cprintf(" * Determining Baud Rate\r\n");
connect(); /* determine baud rate, */
modout(CR); /* tell Tx we got baud right */
mprintf("\r\r\r\r\n FidoNet Version %s\r\n",ver);
mprintf(" FidoNet Node #%u\r\n",mail.node);
mprintf(" Processing mail only.\r\n");
mcrlf();
cprintf(" * Waiting for Sync\r\n");
while (modin(100) != TSYNC)
Fidonet Electronic Mail Protocol 20 Oct 84 Page 20
limitchk();
/* ------------------- End One Minute to Complete -------------------- */
/* All connected. Transfer the mail packet. No time limit, but the
file receive will abort if there is an error. */
limit= 0; /* no time limit */
sprintf(pktname,"%u.in",pktnum++); /* pick a new name, */
cprintf(" * Waiting for Mail Packet (%s)\r\n",pktname);
lprintf(" %s ",pktname);
crcmode= 1; /* CRC, */
filemode= XMODEM; /* file xfer mode, */
recieve(pktname); /* receive a packet, */
msg_pkts= totl_files;
msg_blocks= totl_blocks; /* number of mail packets, */
totl_files= 0;
totl_blocks= 0;
/* Let extra EOTs, etc settle out, then flush it so the file receive
doesnt get the extra EOTs. */
delay(200); /* delay for last char */
while (modin(10) != TIMEOUT);
/* Wait for any incoming files. If there areent any, then the caller
will just hang up if an older version, or will send EOT if no files. */
filemode= TELINK;
recieve(mail.filepath); /* get any files, */
delay(200);
frc_abort(); /* error trap exit */
}
/* Send a mail packet to the remote. Dial the number, if error, return 0 to
indicate no connection. Also, 'minutes' upon return reflects the actual
connection time. */
send_mail() {
char pktname[80],fllname[80];
int n,f;
int msg_pkts,msg_blocks;
int online;
cprintf(" * Calling Fido%u %s %s\r\n",node.number,node.name,node.phone);
online= 0; /* no connect yet */
*_txbuf= '\0'; /* in case no file, */
sprintf(fllname,"%u.fll",node.number);
f= _xopen(fllname,0); /* read in file list, */
n= _xread(f,_txbuf,_TXSIZE);
_txbuf[n]= '\0'; /* null terminate it, */
_xclose(f);
Fidonet Electronic Mail Protocol 20 Oct 84 Page 21
gtod(pktname);
lprintf("Call out Fido%u @ %s\r\n",node.number,pktname);
sprintf(pktname,"%u.out",node.number); /* local packet to send */
++nmap[nn].tries; /* log another try, */
/* We get an abort if (1) it times out dialing, (2) we fail to connect
or (3) transmission sucessful, and receiver hung up. totl_files tells
us what happened. */
totl_blocks= 0;
totl_files= 0;
msg_pkts= 0;
msg_blocks= 0;
set_abort(0);
if (was_abort()) {
if (online) {
nmap[nn].time+= (minutes * 60) + seconds;
++nmap[nn].connects;
}
if (msg_pkts == 0) {
cprintf(" Packet Transmission Aborted\r\n");
lprintf("*Nothing sent\r\n");
} else {
cprintf(" * Sent %u packets %u files\r\n",
msg_pkts,totl_files);
lprintf(" Sent %u pkts %u files\r\n",msg_pkts,totl_files);
nmap[nn].success= 1;
_xdelete(pktname); /* done with that packet */
_xdelete(fllname);
}
cd_flag= 0;
if (dsr()) discon();
return(msg_pkts);
}
/* Set the baud rate from the node list, and dial the number. Dialing is
aborted if either a no-connect from the modem, or a timeout if no modem
is connected. */
rate= 0; /* assume 300 baud, */
if (node.rate >= 1200) rate= 1; /* unless higher */
baud(rate);
cd_flag= 1; /* dont bomb on no carrier */
/* -------------------- One Minute to Dial ---------------------- */
limit= 1; /* 1 min to dial, */
clr_clk(); /* reset the clock, */
if (dial(node.phone) == 0) {
cprintf(" * No connection\r\n");
lprintf("*No connection\r\n");
Fidonet Electronic Mail Protocol 20 Oct 84 Page 22
frc_abort(); /* do abort handler */
}
rate= 0; /* again for stupid hardware */
if (node.rate >= 1200) rate= 1; /* that dials at fixed rates */
baud(rate);
cd_flag= 0; /* now watch carrier */
cprintf(" * Connected at %u baud\r\n",node.rate);
lprintf(" Connect @ %u\r\n",node.rate);
/* -------------------- One Minute to Connect and Sync --------------- */
/* Send CRs until we get a CR back, saying we detected baud correctly. */
online= 1; /* connected now */
clr_clk(); /* reset clock, */
limit= 1; /* 1 min to connect, etc */
/*300*/ while (modin(100) != TIMEOUT) /* quiet line, */
limitchk();
for (n= 8; --n;) { /* limited tries for baud test */
modout(CR); /* send CR CR until we */
/**/ delay(20); /* get one back, */
/**/ modout(CR);
if (modin(100) == CR) break;
}
if (n == 0) {
lprintf("*autobaud failed\r\n");
frc_abort(); /* give up if no response */
}
/* We got a CR from the receiver. Baud rate detected. Now, wait for the
prompt junk to go away, then send our sync character to say we're ready
to send. */
/*100*/ while (modin(50) != TIMEOUT) /* wait for quiet line, */
limitchk();
modout(TSYNC); /* send our sync, */
lprintf(" Sent TSYNC\r\n");
/* -------------------- End One Minute Connect and Sync -------------- */
limit= 0; /* no limit now */
cprintf(" * Sending Packet\r\n");
filemode= XMODEM;
crcmode= 1;
transmit(pktname);
msg_pkts= totl_files;
msg_blocks= totl_blocks;
totl_files= 0;
totl_blocks= 0;
if (strlen(_txbuf) == 0) { /* if no files, just */
Fidonet Electronic Mail Protocol 20 Oct 84 Page 23
modout(EOT); /* send EOT, */
} else {
filemode= TELINK; /* now send any files, */
transmit(_txbuf);
}
delay(500);
frc_abort(); /* do termination code */
}