home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 2 BBS
/
02-BBS.zip
/
orionful.zip
/
Docs
/
Spth.Doc
< prev
next >
Wrap
Text File
|
1996-01-12
|
24KB
|
755 lines
^aSPTH:
A proposal for a 5-D control line for FTN echomail
submitted by AdeptSoft
Current FTN echomail carries two primary types of control lines
dedicated to trying to keep track of where a message has been. One is
the SEEN-BY and the other is the ^aPATH (ref. FTS-0004). Both of these
control lines are fatally flawed for use in today's Fidonet Technology
Networks, or FTN. They are only 2-D (two dimensional addressing, or net
and node), while current addressing technology is 5-D (domain, zone,
net, node and point). Also, ^aPATH lines are NOT required.
What is ^aSPTH?
---------------
The purpose of the proposed ^aSPTH line is to replace the ^aPATH line
with a new, backward compatible 5-D control line that tracks every node
that has processed a message. This is, of course, the function the
^aPATH line had until addressing increased beyond 2-D, rendering ^aPATH
useless.
What do I mean when I say the ^aPATH line is useless? Let's assume
there are two nodes, one in Fidonet and one in Funkynet, with the 4-D
address of 1:65500/1.0 A ^aPATH entry for either of these nodes would
be:
65500/1
Which node is that? For both nodes, one following the other, we'd have
65500/1 1
Which node is which?
This same confusion results from two nodes in the same domain with
identical net and node numbers but different zones.
This same confusion happens when a several points which all have the
same net and node.
Therefore, it is not safe to use ^aPATH lines to see if a message you've
received has been on your system before, or a system to which you're about
to send the message. (Note that 2-D SEEN-BYs suffer from this same
unreliability, but SEEN-BYs are of such MARGINAL usefulness that they
should be eliminated, except for tiny seenbys for backward compatibility
(which should be ignored), not upgraded.) Moreover, when a dupe loop
arises, as they inevitably do due to faulty topology (read: operator
error), the 2-D nature of ^aPATH lines makes it difficult to examine the
topology map (which is what a ^aPATH line is supposed to be used for)
without making many guesses. This situation will only worsen as more
and more zones duplicate net numbers extant in other zones, and domains
duplicate zone and net numbers of other domains. There is nothing
stopping these other zones and domains from doing so, and they should
not have to stop.
In short, we need to fix our control information instead.
^aSPTH can usher in a new "era" of networking using Fidonet technology.
It can allow messages to move freely between zones and domains without
losing the value of either the topology map or dupe elimination. There
are likely to be many other side benefits, such as tracking down domain
or zone gates from the ^aSPTH information.
^aSPTH will allow many artificial restrictions on zone/domain gating to
be removed. For instance, there will be no need to worry about node
numbers from foreign domains appearing in echomail origin lines (or
origin lines themselves, for that matter). Points can forward mail just
like "regular" nodes and still be listed in the topology map. Network
software programmers won't have to worry about where to send a netmail
reply when the ^aMSGID entry is not an FTN address and the FTN domain
name for the foreign net is not obvious from the address portion of the
^aMSGID. Dupe producers can be quickly and accurately pinpointed,
reducing tensions between domains.
What isn't ^aSPTH?
------------------
So much for reasons for existence and benefits. Here's what it isn't:
o ^aSPTH does not change the format of a packet or the packed message.
Reference FTS-0001 for more information on the transport layer.
o ^aSPTH is recommended, but not required, for new echomail processors,
particularly those which serve as zone/domain gates.
What does an ^aSPTH line look like?
-----------------------------------
^aSPTH lines consist of the following:
1) The tag "^aSPTH: " (where the ^a represents ASCII code 1). Note
that ^aSPTH is followed by a colon since FTS-0001 says that it
should be, although none of FTS-0001's examples are.
2) One or more 5-D FTN addresses consisting of domain, zone,
net, node and point (if non-zero) in the format:
Domain#zone:net/node.point
Control lines should be limited to 79 characters or less per line for
esthethic and obliquely technical reasons. Addresses are "sticky,"
which is to say that information duplicated top-down by the previous
entry should not be repeated. For instance, if the first entry's
address is 1:213/760.0@Fidonet and the second is 1:213/100.0@Fidonet, the
^aSPTH line would be:
^aSPTH: Fidonet#1:213/760 100
If we add third and fourth nodes with the addresses 1:213/780@Funkynet
and 1:213/780.1@Funkynet, the line becomes:
^aSPTH: Fidonet#1:213/760 100 Funkynet#1:213/780 .1
This "stickiness" prevents ^aSPTH lines from becoming too large (which
they surely would without it). Other examples are given later on if
you're still confused.
When a new message is exported, the ^aSPTH line should be prepended to
the TOP of the message body with the address of the exporting node. One
address per node, please.
When a message is forwarded, any existing ^aPATH line should be merged
to any existing ^aSPTH line (or, if there is no existing ^aSPTH line,
one should be created), and then the ^aPATH line should be discarded.
Since ^aPATH is 2-D you'll have to guess at the domain and zone portions
of the addresses in the ^aPATH line (assume point is always zero). For
messages with existing ^aSPTH lines, assume the zone and domain have not
changed. For messages without existing ^aSPTH lines, assume your domain
and zone unless you have knowledge of what the appropriate domain and
zone are. After assuring that the ^aSPTH line is up to date, add your
exporting FTN address. By doing this, we can be sure that once zone and
domain gating software utilizes ^aSPTH we will have valid topology maps
even if intermediate nodes do not upgrade (with the possible exception
of points, but points aren't supposed to be forwarding echomail under
the existing system precisely because they're "untraceable.").
Remember, ^aSPTH goes at the top of the message body, not the bottom.
Like ^aPATH, ^aSPTH only lists systems actually processing a message.
It is the set of sending nodes, and does not include the set of sent-to
nodes. Like ^aPATH, ^aSPTH lines are specifically NOT sorted.
^aSPTH lines should NEVER be stripped from a message that is or may be
forwarded.
Note that it is silly to expect ^aSPTH to contain addresses of foreign
(non-FTN) network nodes; they play by their own set of rules. Hopefully
they will preserve our ^aSPTH information and not muck with it.
Following are definitions of the parts of an FTN address as used in
a ^aSPTH line:
Domain - A domain is an alphanumeric [A-Z,0-9] series of ASCII
characters, from one to eight characters long. Domain names
MUST begin with an alphabetic character. They are case
insensitive. Note that a domain name as used in SPTH is not
necessarily the same as a domain used on some other network.
For a common example, "Fidonet" is a valid ^aSPTH domain;
"Fidonet.org" is not, as it is too long and contains a
non-alphanumeric character (the period). Domain names
should be treated case-insensitively.
Zone - A zone is a two-byte integer value (represented as unsigned
decimal for ^aSPTH usage). Valid values range from 1 to
65530 (five values are reserved for possibly strange FTSC
uses).
A zone is preceded by a pound sign. ie. #4
Net - A net is a two-byte integer value as for Zone above.
A net is preceded by a colon. ie. :213
Node - A node is a two-byte integer value as for Zone above, except
that nodes may be numbered 0. Node 0 rarely shows up in
echomail, though, since it's usually reserved for a net's
coordinator and is used for "business" only.
A node is preceded by a slash if it is not preceded by a space.
ie. :213/760 (no space before node number)
or 760 (space before node number)
Point - A point is a two-byte integer value as for Node above.
Remember, point shouldn't be listed if it's 0 as 0 is
always assumed for the point field if it's missing.
A point is preceded by a period. ie. .12
About backward compatibility: since ^aSPTH replaces ^aPATH, you might
think that the information that older processors expect, being
"missing," might cause problems. This is incorrect!!
REMEMBER that the ^aPATH line IS OPTIONAL, and only broken software would
crash due to its absence.
The ^aPATH lines only possible use at this time, due to its
2-D nature and the fact that it is not stripped at domain and zone
gates, as are SEEN-BYs, is as a human-only form of information. ^aSPTH
serves this purpose (as well as others), and does it better. Nothing
breaks, therefore you have backward compatibility.
^aPATH vs. ^aSPTH examples. Note that in all but example #2 the ^aPATH
line is not useable for dupe control (and since ^aPATH is 2-D, you
couldn't even be sure that the addresses in the ^aPATH lines of example
#2 were useable). This should put an end to the "the control lines will
be too long" argument as well as give you a feel for how ^aSPTH can
allow easy, seamless interdomain and interzone messaging. It also
points out rather handily how ^aPATH can quickly become hopelessly
confused due to lack of full address information, and gives you a few
more illustrations for clarity.
Example #1:
Route: (lots of zone traversal)
1:1/1@Fidonet -> 1:1/100@Fidonet -> 1:2/100@Fidonet -> 1:2/1000@Fidonet ->
1:2/1000.50@Fidonet -> 2:1/1@Fidonet -> 2:1/2@Fidonet -> 3:1/1@Fidonet ->
3:1/100@Fidonet -> 3:2/1@Fidonet -> 3:2/2@Fidonet
^aPATH 1/1 100 2/100 1000 1/1 2 1 100 2/1 2
^aSPTH: Fidonet#1:1/1 100 :2/100 1000 .50 #2:1/1 2 #3:1/1 100 :2/1 2
Example #2:
Route: (The addresses in the following are all in Fidonet zone 1
for this example)
1/1 1/2 1/3 1/4 1/5 1/6 1/7 1/8 1/9 1/10 1/11 1/12 1/13 1/14 1/15
2/1 2/2 2/3 2/4 2/5 2/6 2/7 2/8 2/9 2/10 2/11 2/12 2/13 2/14 2/15
^aPATH 1/1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 2/1 2 3 4 5 6 7 8 9
^aPATH 10 11 12 13 14 15
^aSPTH: Fidonet#1:1/1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 :2/1 2 3 4
^aSPTH: 5 6 7 8 9 10 11 12 13 14 15
Example #3:
Route: (lots of domain traversal; "worst" case)
1:1/1@Fidonet ->1:1/1.1@Fidonet -> 2:1/1@Fidonet -> 69:69/1@Funkynet ->
69:69/69@Funkynet -> 1:1/1@Somenet -> 2:1/1@Somenet -> 1:1/1@Othernet ->
2:1/1@Othernet -> 1:1/1@Thatnet -> 2:1/1@Thatnet -> 1:1/1@Thisnet ->
2:1/1@Thisnet -> 3:1/2@Fidonet
^aPATH 1/1 1 69/1 69 1/1 1 1 1 1 1 1 1 2
^aSPTH: Fidonet#1:1/1 .1 #2:1/1 Funkynet#69:69/1 69 Somenet#1:1/1 #2:1/1
^aSPTH: Othernet#1:1/1 #2:1/1 Thatnet#1:1/1 #2:1/1 Thisnet#1:1/1 #2:1/1
^aSPTH: Fidonet#3:1/2
Finally, an example of how to merge existing ^aPATH lines to an existing
^aSPTH:
Existing message control lines:
^aSPTH: Fidonet#1:1/1
...
^aPATH 1/2 3 4/1
Message control lines after being processed by ^aSPTH-aware node
1:5/1.0@Fidonet:
^aSPTH: Fidonet#1:1/1 2 3 :4/1 :5/1
-o-
Credits: Fido and Fidonet are trademarks of Tom Jennings/Fido
Software.
Jeff Rush created echomail.
Bob Hartman wrote FTS-0004 (it's the Confmail doc).
Mark Kimes for the original draft of this document
AdeptSoft
--- example source code ---
typedef struct _ADDR
{
struct _ADDR *next;
USHORT zone;
USHORT net;
USHORT node;
USHORT point;
CHAR *domain;
} ADDR, *PADDR;
typedef struct _PATH
{
USHORT net;
USHORT node;
} PATH, *PPATH;
PADDR ReadSPTH(char *pNewPath)
{
PADDR pHeadOfAddressList;
char lastp;
register char *p;
char *domain = NULL;
char *zone = NULL;
char *net = NULL;
char *node = NULL;
char *point = NULL;
char *lastdomain = NULL;
char *lastzone = NULL;
char *lastnet = NULL;
char *lastnode = NULL;
char *lastpoint = NULL;
if (!pNewPath || !*pNewPath)
return (NULL);
do
{
while (*pNewPath == '\r')
{
pNewPath++;
}
if (!strncmp(pNewPath, "\01SPTH", 5))
{
pNewPath += 5;
if (*pNewPath == ':') // should have colon.. (FTS-0001)
pNewPath++;
pNewPath = SkipWhiteSpace(pNewPath);
while (*pNewPath != '\r' && *pNewPath)
{
pNewPath = SkipWhiteSpace(pNewPath);
if (isdigit(*pNewPath))
{
node = pNewPath;
pNewPath = ToDelimiter(pNewPath, ". \t\r");
if (*pNewPath == '.')
continue;
}
else
{
switch (*pNewPath)
{
case '/':
node = &pNewPath[1];
break;
case ':':
net = &pNewPath[1];
break;
case '#':
zone = &pNewPath[1];
break;
case '.':
point = &pNewPath[1];
pNewPath = ToDelimiter(pNewPath, " \t\r");
goto GotPoint;
default:
if (isalpha(*pNewPath))
domain = pNewPath;
else
{
// This is an error condition
// it signifies a broken mail processor
pNewPath++;
continue;
}
break;
}
if (*pNewPath)
{
pNewPath++;
pNewPath = ToDelimiter(pNewPath, "#:/. \t\r");
if (*pNewPath && strchr("#:/.", *pNewPath))
{
// still more to address
continue;
}
}
}
GotPoint:
if (domain)
lastdomain = domain;
else
domain = lastdomain;
if (zone)
lastzone = zone;
else
zone = lastzone;
if (net)
lastnet = net;
else
net = lastnet;
if (node)
lastnode = node;
else
node = lastnode;
if (point)
lastpoint = point;
else
point = lastpoint;
if (!domain || !zone || !net || !node)
{
continue;
}
// Create entry in list of nodes
// set pHeadOfAddressList.. etc.
}
}
else
break;
} while (*pNewPath && lastdomain && *lastdomain);
return (pHeadOfAddressList);
}
LONG WriteSPTH(PPATH pOldPathInfo, // array of old 2D path info
PADDR pSPTHAddrList, // linked list of current SPTH info
PADDR pMyAddr, // Pointer to our address
FILE *pFile) // where to print info
{
register int OldPathIndex = 0,
register int olen = 0;
register PADDR pCurrAddr;
int len = 0;
USHORT lastnet = 0;
USHORT lastzone = 0,
USHORT lastpoint = 0,
USHORT lastnode = 65535U;
char temp[32];
char oneaddr[80];
char *lastdomain = NULL,
char changed = 0;
long totallen = 0L;
*buffer = 0;
*oneaddr = 0;
pCurrAddr = pSPTHAddrList;
while (pCurrAddr)
{
if (!lastdomain || !*lastdomain || stricmp(pCurrAddr->domain, lastdomain))
{
strcat(oneaddr, " ");
olen++;
strcat(oneaddr, pCurrAddr->domain);
olen += strlen(pCurrAddr->domain);
changed++;
}
if (pCurrAddr->zone != lastzone)
{
if (changed)
{
strcat(oneaddr, "#");
olen++;
}
else
{
strcat(oneaddr, " #");
olen += 2;
}
strcat(oneaddr, ltoa((LONG) pCurrAddr->zone, temp, 10));
olen += strlen(temp);
changed++;
}
if (pCurrAddr->net != lastnet)
{
if (changed)
{
strcat(oneaddr, ":");
olen++;
}
else
{
strcat(oneaddr, " :");
olen += 2;
}
strcat(oneaddr, ltoa((LONG) pCurrAddr->net, temp, 10));
olen += strlen(temp);
changed++;
}
if (pCurrAddr->node != lastnode)
{
if (changed)
{
strcat(oneaddr, "/");
olen++;
}
else
{
strcat(oneaddr, " ");
olen++;
}
strcat(oneaddr, ltoa((LONG) pCurrAddr->node, temp, 10));
olen += strlen(temp);
changed++;
}
if (pCurrAddr->point && lastpoint != pCurrAddr->point)
{
if (changed)
{
strcat(oneaddr, ".");
olen++;
}
else
{
strcat(oneaddr, " .");
olen += 2;
}
strcat(oneaddr, ltoa((LONG) pCurrAddr->point, temp, 10));
olen += strlen(temp);
changed++;
}
if (len + olen > 78)
{
totallen += (LONG) fprintf(pFile, "%s\r", buffer);
len = sprintf(buffer, "\01SPTH:%s", oneaddr);
}
else
{
if (!len)
{
strcpy(buffer, "\01SPTH:");
len = 6;
}
strcat(buffer, oneaddr);
len += olen;
}
*oneaddr = 0;
olen = 0;
changed = 0;
lastpoint = pCurrAddr->point;
lastnode = pCurrAddr->node;
lastnet = pCurrAddr->net;
lastzone = pCurrAddr->zone;
if (pCurrAddr->domain && *pCurrAddr->domain)
lastdomain = pCurrAddr->domain;
pCurrAddr = pCurrAddr->next;
}
if (!pOldPathInfo)
goto SkipOld;
// add old path information. Because of paths 2D information
// this can only be 'best guess' information
olen = 0;
*oneaddr = 0;
lastpoint = 0;
changed = 0;
if (!lastdomain || !*lastdomain)
lastdomain = pMyAddr->domain;
if (!lastzone)
lastzone = pMyAddr->zone;
// do we only have old path information?
if (pOldPathInfo[OldPathIndex].net && !pSPTHAddrList)
{
len = sprintf(buffer, "\01SPTH: %s#%u:%u/%u", lastdomain, lastzone,
pOldPathInfo[OldPathIndex].net, pOldPathInfo[OldPathIndex].node);
lastnet = pOldPathInfo[OldPathIndex].net;
lastnode = pOldPathInfo[OldPathIndex].node;
OldPathIndex++;
}
while (pOldPathInfo[OldPathIndex].net != 0)
{
if (pOldPathInfo[OldPathIndex].net != lastnet)
{
strcat(oneaddr, " :");
olen += 2;
strcat(oneaddr, ltoa((LONG) pOldPathInfo[OldPathIndex].net, temp, 10));
olen += strlen(temp);
changed++;
}
if (pOldPathInfo[OldPathIndex].node != lastnode)
{
if (changed)
{
strcat(oneaddr, "/");
olen++;
}
else
{
strcat(oneaddr, " ");
olen++;
}
strcat(oneaddr, ltoa((LONG) pOldPathInfo[OldPathIndex].node, temp, 10));
olen += strlen(temp);
changed++;
}
if (len + olen > 78)
{
totallen += (LONG) fprintf(pFile, "%s\r", buffer);
len = sprintf(buffer, "\01SPTH:%s", oneaddr);
}
else
{
if (!len)
{
strcpy(buffer, "\01SPTH:");
len = 6;
}
strcat(buffer, oneaddr);
len += olen;
}
*oneaddr = '\0';
olen = 0;
changed = 0;
lastnet = pOldPathInfo[OldPathIndex].net;
lastnode = pOldPathInfo[OldPathIndex].node;
OldPathIndex++;
}
SkipOld:
// Add in our address
*oneaddr = '\0';
olen = 0;
changed = 0;
if (!lastdomain || !*lastdomain || stricmp(pMyAddr->domain, lastdomain))
{
strcat(oneaddr, " ");
olen++;
strcat(oneaddr, pMyAddr->domain);
olen += strlen(pMyAddr->domain);
changed++;
}
if (pMyAddr->zone != lastzone)
{
if (changed)
{
strcat(oneaddr, "#");
olen++;
}
else
{
strcat(oneaddr, " #");
olen += 2;
}
strcat(oneaddr, ltoa((LONG) pMyAddr->zone, temp, 10));
olen += strlen(temp);
changed++;
}
if (pMyAddr->net != lastnet)
{
if (changed)
{
strcat(oneaddr, ":");
olen++;
}
else
{
strcat(oneaddr, " :");
olen += 2;
}
strcat(oneaddr, ltoa((LONG) pMyAddr->net, temp, 10));
olen += strlen(temp);
changed++;
}
if (pMyAddr->node != lastnode)
{
if (changed)
{
strcat(oneaddr, "/");
olen++;
}
else
{
strcat(oneaddr, " ");
olen++;
}
strcat(oneaddr, ltoa((LONG) pMyAddr->node, temp, 10));
olen += strlen(temp);
changed++;
}
if (pMyAddr->point && lastpoint != pMyAddr->point)
{
if (changed)
{
strcat(oneaddr, ".");
olen++;
}
else
{
strcat(oneaddr, " .");
olen += 2;
}
strcat(oneaddr, ltoa((LONG) pMyAddr->point, temp, 10));
olen += strlen(temp);
changed++;
}
if (len + olen > 78)
{
totallen += (LONG) fprintf(pFile, "%s\r", buffer);
len = sprintf(buffer, "\01SPTH:%s", oneaddr);
}
else
{
if (!len)
{
strcpy(buffer, "\01SPTH:");
len = 6;
}
strcat(buffer, oneaddr);
len += olen;
}
*oneaddr = 0;
olen = 0;
changed = 0;
if (len)
totallen += (LONG) fprintf(pFile, "%s\r", buffer);
return totallen;
}