FSC-0011 by Bob Hartman These are some thoughts that I had on FSC001 after implementing things in BinkleyTerm. The state tables I show I believe reflect a little bit more of reality than the older tables. I think that BT corresponds to 99% of the stuff that I wrote, and it can talk to everything that is out there. The biggest thing is to be able to trick everyone currently in existance into doing what they do best without killing someone that can't do all the fancy stuff (ie Fido 11w). Let me know if I can be of any help deciphering any of it. I think it is pretty straightforward. I would prefer if it was not published in FSC001 (since that really should not change, except perhaps for typos and the EOT stuff mentioned below), but this can be an addendum (I'll write something a bit more involved if you want) to be given to developers so that they can be most efficient in transfers with other systems. I just put all this stuff in, and looking at the time (3:33am) I may have goofed in some places. Let me know if you see anything that looks fishy. Let me know if you want me to go any further with this (I probably will anyway, simply as an example of the type of documentation on features that I think would be acceptable in the future). This is the current state table for sending mail: .-----+----------+-------------------------+-------------------------+-----. |State| State | Predicate(s) | Action(s) | Next| | # | Name | | | St | |-----+----------+-------------------------+-------------------------+-----| | S0 | SendInit | | dial modem | S1 | |-----+----------+-------------------------+-------------------------+-----| | S1 | WaitCxD | 1 carrier detected | delay 1-5 seconds | S2 | | | | 2 busy, etc. | report no connection | exit| | | | 3 voice | report no carrier | exit| | | | 4 carrier not detected | report no connection | exit| | | | within 60 seconds | | | |-----+----------+-------------------------+-------------------------+-----| | S2 | WhackCRs | 1 over 30 seconds | report no response | exit| | | | 2 ?? s received | delay 1 sec | S3 | | | | 3 s not received | send | S2 | | | | | delay ??? secs | | |-----+----------+-------------------------+-------------------------+-----| | S3 | WaitClear| 1 no input for 0.5 secs | send TSYNCH = AEH | S4 | | | | 2 over 60 seconds | hang up, report garbage | exit| | | | and line not clear | | | |-----+----------+-------------------------+-------------------------+-----| | S4* | SendMail | | (XMODEM send packet XS0)| S5 | |-----+----------+-------------------------+-------------------------+-----| | S5 | CheckMail| 1 XMODEM successful | (Fido registers success)| S6 | | | | 2 XMODEM fail or timeout| hang up, report mail bad| exit| |-----+----------+-------------------------+-------------------------+-----| | S6* | SendFiles| | (BATCH send files BS0) | S7 | |-----+----------+-------------------------+-------------------------+-----| | S7 | CheckFile| 1 BATCH send successful | | S8 | | | | 2 BATCH send failed | hang up, rept files fail| exit| |-----+----------+-------------------------+-------------------------+-----| | S8 | TryPickup| 1 wish to pickup | note send ok | R2* | | | | 2 no desire to pickup | delay 5 secs | exit| | | | | hang up, rept send ok | | `-----+----------+-------------------------+-------------------------+-----' This note is mentioned: Although the above shows the sender emitting only one TSYNCH, it is recommended that a timeout of 5-20 seconds should initiate another TSYNCH. The receiver should tolerate multiple TSYNCHs. The correct state table should be: .-----+----------+-------------------------+-------------------------+-----. |State| State | Predicate(s) | Action(s) | Next| | # | Name | | | St | |-----+----------+-------------------------+-------------------------+-----| | S0 | SendInit | | dial modem | S1 | |-----+----------+-------------------------+-------------------------+-----| | S1 | WaitCxD | 1 carrier detected | delay 1-5 seconds | S2 | | | | 2 busy, etc. | report no connection | exit| | | | 3 voice | report no carrier | exit| | | | 4 carrier not detected | report no connection | exit| | | | within 60 seconds | | | |-----+----------+-------------------------+-------------------------+-----| | S2 | WhackCRs | 1 over 30 seconds | report no response | exit| | | | 2 ?? s received | delay 1 sec | S3 | | | | 3 s not received | send | S2 | | | | | delay ??? secs | | |-----+----------+-------------------------+-------------------------+-----| | S3 | WaitClear| 1 no input for 0.5 secs | send TSYNCH = AEH | S4 | | | | 2 over 60 seconds | hang up, report garbage | exit| | | | and line not clear | | | |-----+----------+-------------------------+-------------------------+-----| | S4* | TSyncChk | 1 'C' or NAK (peeked at)| (XMODEM send packet XS1)| S5 | | | | 2 over 2 seconds | eat noise, resend TSync | S4 | | | | 3 over 30 seconds | hang up report not Fido | exit| |-----+----------+-------------------------+-------------------------+-----| | S5 | CheckMail| 1 XMODEM successful | (Fido registers success)| S6 | | | | 2 XMODEM fail or timeout| hang up, report mail bad| exit| |-----+----------+-------------------------+-------------------------+-----| | S6* | SendFiles| | (BATCH send files BS0) | S7 | |-----+----------+-------------------------+-------------------------+-----| | S7 | CheckFile| 1 BATCH send successful | | S8 | | | | 2 BATCH send failed | hang up, rept files fail| exit| |-----+----------+-------------------------+-------------------------+-----| | S8 | TryPickup| 1 wish to pickup | note send ok | R2* | | | | 2 no desire to pickup | delay 5 secs | exit| | | | | hang up, rept send ok | | `-----+----------+-------------------------+-------------------------+-----' In state S4, the phrase "peeked at" means that the character is not removed from the buffer. Therefore when XS1 is started the proper character for beginning the Xmodem transfer will be detected. Notice also that XS1 is a change from the XS0 that is given in the original. XS0 is for doing Telink, not Xmodem. Since the first part (the mail packet) is sent Xmodem, the proper place to enter is XS1 (I think). This next is the current table for Xmodem receiving: XMODEM/TeLink Receiver .-----+----------+-------------------------+-------------------------+-----. |State| State | Predicate(s) | Action(s) | Next| | # | Name | | | St | |-----+----------+-------------------------+-------------------------+-----| | XR0 | RecStart | 1 prefer crc mode | Send "C" | XR1 | | | | 2 want checksum mode | send NAK | XR1 | |-----+----------+-------------------------+-------------------------+-----| | XR1 | WaitFirst| 1 10 retries or 1 minute| report receive failure | exit| | | | 2 > 3 retries or 30 secs| set want checksum mode | XR0 | | | | 3 EOT received | send ACK, report no file| exit| | | | 4 TeLink block recd | send ACK, set crc/cksm | XR2 | | | | 5 data block recd | send ACK, set crc/cksm | XR2 | | | | 6 bad block or 2-10 secs| incr retry count | XR0 | |-----+----------+-------------------------+-------------------------+-----| | XR2 | WaitBlock| 1 10 retries or 1 minute| report receive failure | exit| | | | 2 EOT received | send ACK, report recd ok| exit| | | | 3 data block received | send ACK | XR2 | | | | 4 bad block or 2-10 secs| send NAK, incr retry cnt| XR2 | `-----+----------+-------------------------+-------------------------+-----' The following inserts the small fix I mentioned in FTSC about the EOT probs: XMODEM/TeLink Receiver .-----+----------+-------------------------+-------------------------+-----. |State| State | Predicate(s) | Action(s) | Next| | # | Name | | | St | |-----+----------+-------------------------+-------------------------+-----| | XR0 | RecStart | 1 prefer crc mode | Send "C" | XR1 | | | | 2 want checksum mode | send NAK | XR1 | |-----+----------+-------------------------+-------------------------+-----| | XR1 | WaitFirst| 1 10 retries or 1 minute| report receive failure | exit| | | | 2 > 3 retries or 30 secs| set want checksum mode | XR0 | | | | 3 EOT received | delay 1 sec, purge input| exit| | | | | send ACK, report no file| | | | | 4 TeLink block recd | send ACK, set crc/cksm | XR2 | | | | 5 data block recd | send ACK, set crc/cksm | XR2 | | | | 6 bad block or 2-10 secs| incr retry count | XR0 | |-----+----------+-------------------------+-------------------------+-----| | XR2 | WaitBlock| 1 10 retries or 1 minute| report receive failure | exit| | | | 2 EOT received | delay 1 sec, purge input| exit| | | | | send ACK, report recd ok| | | | | 3 data block received | send ACK | XR2 | | | | 4 bad block or 2-10 secs| send NAK, incr retry cnt| XR2 | `-----+----------+-------------------------+-------------------------+-----' As I mentioned in the FTSC conference, the delay to eat characters is needed in order to purge the extra EOT's that some software sends out. The delay can be shorter than 1 second (in practice 2/10ths seems to work well), but 1 sec fit nicely in the little box. This is the current Modem7 filename sender: MODEM7 Filename Sender .-----+----------+-------------------------+-------------------------+-----. |State| State | Predicate(s) | Action(s) | Next| | # | Name | | | St | |-----+----------+-------------------------+-------------------------+-----| | MS0 | WaitNak | 1 20 retries or 1 minute| filename send failed | exit| | | | 2 NAK received | send ACK & 1st ch of fn | MS1 | |-----+----------+-------------------------+-------------------------+-----| | MS1 | WaitChAck| 1 ACK rcd, fname done | send SUB = 1AH | MS2 | | | | 2 ACK rcd, fname ~done | send next ch of fname | MS1 | | | | 3 other char or 1 sec | send "u", incr retry cnt| MS0 | |-----+----------+-------------------------+-------------------------+-----| | MS2 | WaitCksm | 1 cksum recd and ok | send ACK, report fn ok | exit| | | | 2 cksum recd but bad | send "u", incr retry cnt| MS0 | | | | 3 no cksum in 1 sec | send "u", incr retry cnt| MS0 | `-----+----------+-------------------------+-------------------------+-----' The drawbacks of this one are that it does not take into account the possibility of a SEAdog at the other end (or other software) that does not wish to do Modem7 filename transfer. The other end will send a "C" instead of the usual NAK, and that should be accounted for: MODEM7 Filename Sender .-----+----------+-------------------------+-------------------------+-----. |State| State | Predicate(s) | Action(s) | Next| | # | Name | | | St | |-----+----------+-------------------------+-------------------------+-----| | MS0 | WaitNak | 1 20 retries or 1 minute| filename send failed | exit| | | | 2 NAK received | send ACK & 1st ch of fn | MS1 | | | | 3 C received | return fn skipped | exit| |-----+----------+-------------------------+-------------------------+-----| | MS1 | WaitChAck| 1 ACK rcd, fname done | send SUB = 1AH | MS2 | | | | 2 ACK rcd, fname ~done | send next ch of fname | MS1 | | | | 3 other char or 1 sec | send "u", incr retry cnt| MS0 | |-----+----------+-------------------------+-------------------------+-----| | MS2 | WaitCksm | 1 cksum recd and ok | send ACK, report fn ok | exit| | | | 2 cksum recd but bad | send "u", incr retry cnt| MS0 | | | | 3 no cksum in 1 sec | send "u", incr retry cnt| MS0 | `-----+----------+-------------------------+-------------------------+-----' If a C is received, it should trigger that the other end does not wish to do a Modem7 filename transfer. Since the data in a Telink header block (as well as SEAlink header block) makes the Modem7 filename redundant, the sender can return a good filename and slip into Telink send with no problem. Substituting SEAlink send for Telink send is also a viable possibility. Currently this is the state machine for Modem7 receiver: MODEM7 Filename Receiver .-----+----------+-------------------------+-------------------------+-----. |State| State | Predicate(s) | Action(s) | Next| | # | Name | | | St | |-----+----------+-------------------------+-------------------------+-----| | MR0 | SendNak | 1 20 tries or 1 minute | report filename failure | exit| | | | 2 | send NAK, incr try cnt | MR1 | |-----+----------+-------------------------+-------------------------+-----| | MR1 | WaitAck | 1 rcd ACK | | MR2 | | | | 2 rcd EOT | report no files remain | exit| | | | 3 5 secs & no ACK/EOT | | MR0 | |-----+----------+-------------------------+-------------------------+-----| | MR2 | WaitChar | 1 recd EOT (can happen?)| report no files remain | exit| | | | 2 recd SUB | send checksum byte | MR3 | | | | 3 recd "u" | | MR0 | | | | 4 recd char of name | send ACK | MR2 | | | | 5 no char in 1 second | | MR0 | |-----+----------+-------------------------+-------------------------+-----| | MR3 | WaitOkCk | 1 recd ACK within 1 sec | report recd filename ok | exit| | | | 2 recd "u" or other char| | MR0 | `-----+----------+-------------------------+-------------------------+-----' To get rid of the necessity for the Modem7 filename, do the following: MODEM7 Filename Receiver .-----+----------+-------------------------+-------------------------+-----. |State| State | Predicate(s) | Action(s) | Next| | # | Name | | | St | |-----+----------+-------------------------+-------------------------+-----| | MR0 | SendC | 1 5 tries | cannot skip, must do it | MR0b| | | | 2 | send C , incr try cnt | MR0a| |-----+----------+-------------------------+-------------------------+-----| | MR0a| WaitSkip | 1 SOH or SYN peeked at | return fname skipped | exit| | | | 2 1 second passes | | MR0 | | | | 3 other char received | eat character | MR0 | |-----+----------+-------------------------+-------------------------+-----| | MR0b| SendNak | 1 20 tries or 1 minute | report filename failure | exit| | | | 2 | send NAK, incr try cnt | MR1 | |-----+----------+-------------------------+-------------------------+-----| | MR1 | WaitAck | 1 rcd ACK | | MR2 | | | | 2 rcd EOT | report no files remain | exit| | | | 3 5 secs & no ACK/EOT | | MR0 | |-----+----------+-------------------------+-------------------------+-----| | MR2 | WaitChar | 1 recd EOT (can happen?)| report no files remain | exit| | | | 2 recd SUB | send checksum byte | MR3 | | | | 3 recd "u" | | MR0 | | | | 4 recd char of name | send ACK | MR2 | | | | 5 no char in 1 second | | MR0 | |-----+----------+-------------------------+-------------------------+-----| | MR3 | WaitOkCk | 1 recd ACK within 1 sec | report recd filename ok | exit| | | | 2 recd "u" or other char| | MR0 | `-----+----------+-------------------------+-------------------------+-----' This allows the filename receiver to notice that he has triggered the other system into skipping the Modem7 filename stuff. Once that happens, as in the Modem7 sender, the filename can be done away with and simple Telink or SEAlink transfer can commence. Note that once again, the byte received is peeked at, so that it can remain in the buffer to start the Telink/SEAlink transfer. Returning fname skipped, rather than fname ok signals the other states not to send an originating NAK (see below): BATCH File Receiver .-----+----------+-------------------------+-------------------------+-----. |State| State | Predicate(s) | Action(s) | Next| | # | Name | | | St | |-----+----------+-------------------------+-------------------------+-----| | BR0*| RecvName | | (MODEM7 FName recv MR0) | BR1 | |-----+----------+-------------------------+-------------------------+-----| | BR1 | CheckFNm | 1 MODEM7 no more files | report files recd ok | exit| | | | 2 MODEM7 Filename ok | (TeLink recv file XR0) | BR2 | | | | 3 MODEM7 Filename skip | (TeLink recv file XR1) | BR2 | | | | 4 MODEM7 Filename bad | report name recv bad | exit| |-----+----------+-------------------------+-------------------------+-----| | BR2 | CheckFile| 1 TeLink recv ok | | BR0 | | | | 2 TeLink recv bad | report file recv bad | exit| `-----+----------+-------------------------+-------------------------+-----' Now, the sender must also have a slight adjustment: BATCH File Sender .-----+----------+-------------------------+-------------------------+-----. |State| State | Predicate(s) | Action(s) | Next| | # | Name | | | St | |-----+----------+-------------------------+-------------------------+-----| | BS0*| MoreFiles| 1 more files to send | (MODEM7 FName send MS0) | BS1 | | | | 2 no more files to send | | BS3 | |-----+----------+-------------------------+-------------------------+-----| | BS1 | CheckFNm | 1 MODEM7 Filename ok | (TeLink send file XS0) | BS2 | | | | 2 MODEM7 Filename skip | (Telink send file XS0a) | BS2 | | | | 3 MODEM7 Filename bad | report name send bad | exit| |-----+----------+-------------------------+-------------------------+-----| | BS2 | CheckFile| 1 TeLink send ok | | BS0 | | | | 2 TeLink send bad | report file send bad | exit| |-----+----------+-------------------------+-------------------------+-----| | BS3 | EndSend | 1 rec NAK for next file | send EOT, report send ok| exit| | | | 2 10 seconds no NAK | send EOT, report no NAK | exit| `-----+----------+-------------------------+-------------------------+-----' Here is the modified Xmodem sender: XMODEM/TeLink Sender .-----+----------+-------------------------+-------------------------+-----. |State| State | Predicate(s) | Action(s) | Next| | # | Name | | | St | |-----+----------+-------------------------+-------------------------+-----| | XS0a| SendTeLnk| | send TeLink, incr tries | XS0 | |-----+----------+-------------------------+-------------------------+-----| | XS0 | WaitTeLnk| 1 over 40-60 seconds | report sender timeout | exit| | | | 2 over 2 tries | note TeLink block failed| XS1 | | | | 3 NAK or "C" received | send TeLink, incr tries | XS0 | | | | 4 ACK received | TeLink ok, set crc/cksm | XS2 | |-----+----------+-------------------------+-------------------------+-----| | XS1 | WaitStart| 1 over 40-60 seconds | report sender timeout | exit| | | | 2 over 20 tries | report send failed | exit| | | | 3 NAK received | set checksum mode | XS2 | | | | 4 "C" recd, I can crc | set crc mode | XS2 | | | | 5 "C" recd, I can't crc | | XS1 | |-----+----------+-------------------------+-------------------------+-----| | XS2 | SendBlock| 1 more data available | send next data block | XS3 | | | | | as checksum or crc | | | | | 2 last block has gone | send EOT | XS4 | |-----+----------+-------------------------+-------------------------+-----| | XS3 | WaitACK | 1 10 retries or 1 minute| report send failed | exit| | | | 2 ACK received | | XS2 | | | | 3 NAK (or C if 1st blk) | resend last block | XS3 | |-----+----------+-------------------------+-------------------------+-----| | XS4 | WaitEnd | 1 10 retries or 1 minute| report send failed | exit| | | | 2 ACK received | report send successful | exit| | | | 3 NAK received | resend EOT | XS4 | `-----+----------+-------------------------+-------------------------+-----'