home *** CD-ROM | disk | FTP | other *** search
-
- ^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;
- }
-