home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------------*/
- /* */
- /* */
- /* ------------ Bit-Bucket Software, Co. */
- /* \ 10001101 / Writers and Distributors of */
- /* \ 011110 / Freely Available<tm> Software. */
- /* \ 1011 / */
- /* ------ */
- /* */
- /* (C) Copyright 1987-91, Bit Bucket Software Co., a Delaware Corporation. */
- /* */
- /* */
- /* This module was written by Bob Hartman */
- /* */
- /* */
- /* BinkleyTerm Xmodem Sender State Machine */
- /* */
- /* */
- /* For complete details of the licensing restrictions, please refer */
- /* to the License agreement, which is published in its entirety in */
- /* the MAKEFILE and BT.C, and also contained in the file LICENSE.250. */
- /* */
- /* USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE */
- /* BINKLEYTERM LICENSING AGREEMENT. IF YOU DO NOT FIND THE TEXT OF */
- /* THIS AGREEMENT IN ANY OF THE AFOREMENTIONED FILES, OR IF YOU DO */
- /* NOT HAVE THESE FILES, YOU SHOULD IMMEDIATELY CONTACT BIT BUCKET */
- /* SOFTWARE CO. AT ONE OF THE ADDRESSES LISTED BELOW. IN NO EVENT */
- /* SHOULD YOU PROCEED TO USE THIS FILE WITHOUT HAVING ACCEPTED THE */
- /* TERMS OF THE BINKLEYTERM LICENSING AGREEMENT, OR SUCH OTHER */
- /* AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO. */
- /* */
- /* */
- /* You can contact Bit Bucket Software Co. at any one of the following */
- /* addresses: */
- /* */
- /* Bit Bucket Software Co. FidoNet 1:104/501, 1:343/491 */
- /* P.O. Box 460398 AlterNet 7:491/0 */
- /* Aurora, CO 80046 BBS-Net 86:2030/1 */
- /* Internet f491.n343.z1.fidonet.org */
- /* */
- /* Please feel free to contact us at any time to share your comments about */
- /* our software and/or licensing policies. */
- /* */
- /*--------------------------------------------------------------------------*/
-
- /* Include this file before any other includes or defines! */
-
- #include "includes.h"
-
- void Build_Header_Block (XMARGSP args, char type)
- {
- struct FILEINFO dta;
- SEADATAP ttmp;
-
- (void) dfind (&dta, args->filename, 0);
- args->save_header = type;
- ttmp = (SEADATAP) &(args->header);
-
- (void) memset (ttmp, 0, sizeof (XMDATA));
- ttmp->header = type;
- ttmp->block_num = 0;
- ttmp->block_num_comp = 0xff;
- ttmp->filelength = args->filelen;
- (void) strncpy (ttmp->sendingprog, xfer_id, 14);
- if (type == SYN)
- {
- (void) memset (ttmp->filename, ' ', 16);
- ttmp->timedate = dta.time;
- /* This is the CRC bit in the TeLink header */
- ttmp->Resync = 1;
- }
- else
- {
- ttmp->timedate = args->save_filetime.oneword.timedate;
- ttmp->SLO = (unsigned char) (((cur_baud.rate_value >= 9600) && !no_overdrive)? 1 : 0);
- ttmp->Resync = (unsigned char) (no_resync ? 0 : 1);
- ttmp->MACFLOW = 1;
- }
- if (args->temp_name != NULL)
- (void) strncpy (ttmp->filename, args->temp_name, strlen (args->temp_name));
- else
- (void) strncpy (ttmp->filename, (char *) (dta.name), strlen (dta.name));
- }
-
- void XSSetVars (XMARGSP);
- int XSInit (XMARGSP, int);
- int XSEnd (XMARGSP, int);
- int XSXmtStart (XMARGSP);
- int XSXmTeStrt (XMARGSP);
- int XSCheckACK (XMARGSP);
- int XSSendBlk (XMARGSP);
- int XSWaitEnd (XMARGSP);
-
- STATES Xmodem_Sender[] = {
- { "XSInit", XSInit },
- { "XSEnd", XSEnd },
- { "XS0", XSXmtStart },
- { "XS0T", XSXmTeStrt },
- { "XS1", XSCheckACK },
- { "XS2", XSSendBlk },
- { "XS3", XSWaitEnd }
- };
-
- int XSInit (XMARGSP args, int start_state)
- {
- struct stat st;
- char junkbuff[100];
-
- /* Get the file information */
- if (stat (args->filename, &st))
- {
- /* Print error message */
- return (OPEN_ERR);
- }
-
- if ((args->file_pointer = share_fopen (args->filename, "rb", DENY_WRITE)) == NULL)
- {
- /* Print error message */
- return (OPEN_ERR);
- }
-
- /* Get important information out of it */
- args->filelen = st.st_size;
- args->LastBlk = (st.st_size + 127) / 128;
- args->save_filetime.oneword.timedate = st.st_atime;
- args->prev_bytes = 0L;
- args->tot_errs = 0;
-
- (void) sprintf (junkbuff, MSG_TXT(M_SEND_MSG), args->LastBlk, args->filename, st.st_size);
- if (un_attended && fullscreen)
- {
- clear_filetransfer ();
- sb_move (file_hWnd, 1, 2);
- FlLnModeSet( FILE_LN_2, 1 );
- sb_puts( GetDlgItem( file_hWnd, FILE_LN_1 ), junkbuff );
- elapse_time ();
- sb_show ();
- }
- else
- {
- status_line ("+%s", junkbuff);
- (void) printf ("\n");
- }
-
- locate_y = wherey ();
- locate_x = wherex ();
-
- /* Start the throughput calculations */
- throughput (0, 0L);
- return (start_state);
- }
-
- int XSEnd (XMARGSP args, int cur_state)
- {
- args->result = cur_state;
-
- /* Close file */
- (void) fclose (args->file_pointer);
-
- if (args->tot_errs > 3)
- status_line (MSG_TXT(M_CORRECTED_ERRORS), args->tot_errs, args->LastBlk);
-
- /* Log that we sent it */
- if (cur_state == SUCCESS)
- {
- throughput (1, (unsigned long) (args->filelen - args->prev_bytes));
- status_line ("%s: %s", MSG_TXT(M_FILE_SENT), args->filename);
- update_files (1);
- }
-
- return (cur_state);
- }
-
- void XSSetVars (XMARGSP args)
- {
- if (no_sealink)
- {
- args->options.SLO = 0;
- args->options.Resync = 0;
- }
- else
- {
- args->options.SLO = ((cur_baud.rate_value >= 9600) && !no_overdrive) ? 1 : 0;
- args->options.Resync = (~no_resync) & 1;
- }
-
- args->options.SEAlink = 0;
- args->SendBLK = 1;
- args->curr_byte = 0L;
- args->NextBLK = 1;
- args->ACKST = 0;
- args->ACKBLK = -1L;
- args->Window = 1;
- args->ACKsRcvd = 0;
- args->NumNAK = 0;
- args->T1 = timerset (3000);
- }
-
- int XSXmtStart (XMARGSP args)
- {
- XSSetVars (args);
- Build_Header_Block (args, SOH);
- return (XS1);
- }
-
- int XSXmTeStrt (XMARGSP args)
- {
- XSSetVars (args);
- Build_Header_Block (args, SYN);
- return (XS1);
- }
-
- int XSCheckACK (XMARGSP args)
- {
- Check_ACKNAK (args);
- return (XS2);
- }
-
- int XSSendBlk (XMARGSP args)
- {
- if (!CARRIER)
- return (CARRIER_ERR);
-
- if (got_ESC ())
- {
- status_line (MSG_TXT(M_KBD_MSG));
- return (KBD_ERR);
- }
-
- if ((args->NumNAK > 4) && (args->SendBLK == 0))
- {
- if (args->save_header == SOH)
- return (XS0T);
- else
- {
- args->NumNAK = 0;
- ++(args->ACKBLK);
- ++(args->SendBLK);
- return (XS2);
- }
- }
-
- if (args->NumNAK > 10)
- {
- /* Too Many Errors */
- return (SEND_RETRY_ERR);
- }
-
- if (timeup (args->T1))
- {
- /* Fatal Timeout */
- return (SEND_TIMEOUT);
- }
-
- if (args->SendBLK > (args->LastBlk + 1))
- return (XS3);
-
- if (args->SendBLK > (args->ACKBLK + args->Window))
- {
- time_release ();
- return (XS1);
- }
-
- if (args->SendBLK == (args->LastBlk + 1))
- {
- SENDBYTE (EOT);
- ++(args->SendBLK);
- args->T1 = timerset (3000);
- show_sending_blocks (args);
- time_release ();
- return (XS1);
- }
-
- /*
- Increment the block count before sending because we read the next
- block immediately after sending this block. On error free connects
- we have a big net win because we never do a seek, and while we are
- sending one block, we read the next. If we do get errors, then we
- have to seek back to the previous block, and that will be a bother.
- With today's phone lines and modems, we'll assume error free is more
- often than not, and take our chances.
- */
- if (args->options.SLO && args->options.SEAlink)
- {
- args->ACKBLK = args->SendBLK;
- }
-
- ++(args->SendBLK);
- args->curr_byte += 128L;
- Send_Block (args);
- args->T1 = timerset (6000);
- return (XS1);
- }
-
- int XSWaitEnd (XMARGSP args)
- {
- show_sending_blocks (args);
-
- if (args->ACKBLK < (args->LastBlk + 1))
- {
- time_release ();
- return (XS1);
- }
-
- if (!CARRIER)
- return (CARRIER_ERR);
-
- return (SUCCESS);
- }
-
- int SEAlink_Send_File (char *filename, char *sendname)
- {
- XMARGS xm;
-
- xm.filename = filename;
- xm.temp_name = sendname;
- return (state_machine (Xmodem_Sender, &xm, XS0));
- }
-
- int Xmodem_Send_File (char *filename, char *sendname)
- {
- return (SEAlink_Send_File (filename, sendname));
- }
-
- int Telink_Send_File (char *filename, char *sendname)
- {
- XMARGS xm;
-
- xm.filename = filename;
- xm.temp_name = sendname;
- return (state_machine (Xmodem_Sender, &xm, XS0T));
- }
-
- void Get_Block (XMARGSP args)
- {
- XMDATAP xtmp;
-
- if (args->SendBLK == 0)
- {
- Build_Header_Block (args, args->save_header);
- args->NextBLK = -1L;
- return;
- }
-
- xtmp = (XMDATAP) &(args->header);
-
- /* Set up buffer as all ^Zs for EOF */
- (void) memset (xtmp, SUB, sizeof (XMDATA));
-
- /* Now set up the header stuff */
- xtmp->header = SOH;
- xtmp->block_num = (unsigned char) (args->SendBLK & 0xff);
- xtmp->block_num_comp = (unsigned char)~xtmp->block_num;
-
- if (args->NextBLK != args->SendBLK)
- {
- (void) fseek (args->file_pointer, (args->SendBLK - 1) * 128, SEEK_SET);
- }
-
- args->NextBLK = args->SendBLK + 1;
-
- /* Can we read any data? */
- if (fread ((char *) xtmp->data_bytes, 1, 128, args->file_pointer) <= 0)
- return;
-
- /* Looks good */
- return;
- }
-
- void Send_Block (XMARGSP args)
- {
- if (args->header == SYN)
- {
- Data_Check ((XMDATAP) &(args->header), CHECKSUM);
- }
- else
- {
- Data_Check ((XMDATAP) &(args->header), args->options.do_CRC ? CRC : CHECKSUM);
- }
-
- if ((!(args->options.do_CRC)) || (args->header == SYN))
- {
- SENDCHARS ((char *) &(args->header), sizeof (XMDATA) - 1, 1);
- }
- else
- {
- SENDCHARS ((char *) &(args->header), sizeof (XMDATA), 1);
- }
-
- UNBUFFER_BYTES ();
-
- show_sending_blocks (args);
-
- Get_Block (args);
- }
-
- char *show_num (XMARGSP args, long b)
- {
- char *Rtn;
-
- Rtn = "EOT";
- if (b > args->LastBlk)
- {
- if (!(fullscreen && un_attended))
- (void) cputs (Rtn);
- }
- else if (b >= 0L)
- {
- Rtn = ultoa (((unsigned long) b), e_input, 10);
- if (!(fullscreen && un_attended))
- (void) cputs (Rtn);
- }
- return Rtn;
- }
-
- void show_sending_blocks (XMARGSP args)
- {
- char *TmpPtr = (char *)&happy_compiler;
- char j[100];
- int i;
- long k;
-
- k = args->filelen - args->curr_byte;
- if (k < 0L)
- k = 0L;
-
- i = (int) ((k * 10 / cur_baud.rate_value * 100 /
- ((args->save_header == SOH) ? 94 : 70) + 59) / 60);
- (void) sprintf (j, "%3d min", i);
-
- if (args->options.SLO)
- {
- if ((!((args->SendBLK - 1) & 0x1f)) || ((args->SendBLK - 1) > args->LastBlk))
- {
- if (fullscreen && un_attended)
- {
- elapse_time();
- sb_move (file_hWnd, 2, 2);
- TmpPtr = show_num (args, args->SendBLK - 1);
- sb_puts( GetDlgItem( file_hWnd, FILE_LN_2 + GD_TOTAL ),
- TmpPtr );
- #ifndef MILQ
- (void) sb_putc (file_hWnd, ':');
- #endif
- TmpPtr = show_num (args, args->ACKBLK);
- sb_puts( GetDlgItem( file_hWnd, FILE_LN_2 + GD_SIZE ),
- TmpPtr );
- sb_puts( GetDlgItem( file_hWnd, FILE_LN_2 + GD_STATUS ),
- " *Overdrive* ");
- sb_move (file_hWnd, 2, 69);
- sb_puts( GetDlgItem( file_hWnd, FILE_LN_2 + GD_DTTM ), j );
- sb_show ();
- }
- else
- {
- gotoxy (locate_x, locate_y);
- (void) show_num (args, args->SendBLK - 1);
- (void) cputs (":");
- (void) show_num (args, args->ACKBLK);
- (void) cputs (" *Overdrive* ");
- }
- }
- }
- else
- {
- if (fullscreen && un_attended)
- {
- elapse_time();
-
- sb_move (file_hWnd, 2, 2);
- TmpPtr = show_num (args, args->SendBLK - 1);
- sb_puts( GetDlgItem( file_hWnd, FILE_LN_2 + GD_TOTAL ),
- TmpPtr );
- #ifndef MILQ
- (void) sb_putc (file_hWnd, ':');
- #endif
- TmpPtr = show_num (args, args->ACKBLK);
- sb_puts( GetDlgItem( file_hWnd, FILE_LN_2 + GD_SIZE ),
- TmpPtr );
-
- #ifndef MILQ
- sb_puts (file_hWnd, " ");
- #endif
- sb_move (file_hWnd, 2, 69);
- sb_puts( GetDlgItem( file_hWnd, FILE_LN_2 + GD_DTTM ), j );
- sb_show ();
- }
- else
- {
- gotoxy (locate_x, locate_y);
- (void) show_num (args, args->SendBLK - 1);
- (void) cputs (":");
- (void) show_num (args, args->ACKBLK);
- (void) cputs (" ");
- }
- }
- happy_compiler = * (int *) TmpPtr; /* Makes the compiler happy! */
- }
-
- int ACInit (XMARGSP, int);
- int ACEnd (XMARGSP, int);
- int ACChkRcvd (XMARGSP);
- int ACSLCheck (XMARGSP);
- int ACSLVerify (XMARGSP);
- int ACSLACKNAK (XMARGSP);
- int ACXMCheck (XMARGSP);
- int ACSLOCheck (XMARGSP);
- int ACSL1Check (XMARGSP);
- int ACACKNAK (XMARGSP);
- int ACXMACK (XMARGSP);
- int ACXMNAK (XMARGSP);
- int ACRESYNC (XMARGSP);
-
- STATES ACKNAK_Check[] = {
- { "ACInit", ACInit },
- { "ACEnd", ACEnd },
- { "AC0", ACChkRcvd },
- { "AC1", ACSLCheck },
- { "AC2", ACSLVerify },
- { "AC3", ACSLACKNAK },
- { "AC4", ACXMCheck },
- { "AC5", ACSLOCheck },
- { "AC6", ACSL1Check },
- { "AC7", ACACKNAK },
- { "AC8", ACXMACK },
- { "AC9", ACXMNAK },
- { "AC10", ACRESYNC }
- };
-
- int ACInit (XMARGSP args, int start_state)
- {
- args->result = 0;
- return (start_state);
- }
-
- int ACEnd (XMARGSP args, int cur_state)
- {
- args->result = cur_state;
- return (cur_state);
- }
-
- int ACChkRcvd (XMARGSP args)
- {
- if (PEEKBYTE () >= 0)
- {
- args->CHR = TIMED_READ (0);
- return (AC1);
- }
-
- return (SUCCESS);
- }
-
- int ACSLCheck (XMARGSP args)
- {
- if (args->ACKST > 2)
- return (AC2);
-
- return (AC6);
- }
-
- int ACSLVerify (XMARGSP args)
- {
- if (args->ARBLK8 == (unsigned char) ((~args->CHR) & 0xff))
- {
- args->ARBLK = args->SendBLK - ((args->SendBLK - args->ARBLK8) & 0xff);
- return (AC3);
- }
-
- args->options.SEAlink = 0;
- args->Window = 1;
- args->ACKST = 0;
- return (AC6);
- }
-
- int ACSLACKNAK (XMARGSP args)
- {
- if ((args->ARBLK < 0)
- || (args->ARBLK > args->SendBLK)
- || (args->ARBLK <= (args->SendBLK - 128)))
- {
- return (AC0);
- }
-
- if (args->ACKST == 3)
- {
- args->options.SEAlink = (~no_sealink) & 1;
- args->Window = calc_window ();
- args->ACKBLK = args->ARBLK;
- ++(args->ACKsRcvd);
- args->ACKST = 0;
- return (AC5);
- }
-
- args->SendBLK = args->ARBLK;
- args->curr_byte = (args->SendBLK - 1) * 128L;
- if (args->curr_byte < 0L)
- args->curr_byte = 0L;
-
- if (args->SendBLK > 0)
- ++(args->tot_errs);
-
- Get_Block (args);
- args->ACKST = 0;
-
- return (AC4);
- }
-
- int ACXMCheck (XMARGSP args)
- {
- if (args->NumNAK < 4)
- {
- args->options.SEAlink = (~no_sealink) & 1;
- args->Window = calc_window ();
- }
- else
- {
- args->options.SEAlink = 0;
- args->Window = 1;
- }
- return (SUCCESS);
- }
-
- int ACSLOCheck (XMARGSP args)
- {
- if ((args->options.SLO == 0) || (args->ACKsRcvd < 10))
- return (SUCCESS);
-
- args->options.SLO = 0;
- return (SUCCESS);
- }
-
- int ACSL1Check (XMARGSP args)
- {
- if ((args->ACKST == 1) || (args->ACKST == 2))
- {
- args->ARBLK8 = (unsigned char) args->CHR;
- args->ACKST += 2;
- return (AC6);
- }
-
- if ((args->options.SEAlink == 0) || (args->ACKST == 0))
- return (AC7);
-
- return (AC0);
- }
-
- int ACACKNAK (XMARGSP args)
- {
- long mac_timer;
-
- switch (args->CHR)
- {
- case ACK:
- args->ACKST = 1;
- args->NumNAK = 0;
- return (AC8);
-
- case WANTCRC:
- args->options.do_CRC = 1;
- /* Fallthrough */
-
- case NAK:
- args->ACKST = 2;
- ++(args->NumNAK);
- CLEAR_OUTBOUND ();
- timer (6);
- return (AC9);
-
- case SYN:
- CLEAR_OUTBOUND ();
- if (!no_resync)
- {
- args->result = Receive_Resync (&(args->resync_block));
- args->ACKST = 0;
- return (AC10);
- }
- else
- {
- return (AC0);
- }
-
- case DC3: /* ^S */
- if (args->options.SEAlink && (args->ACKST == 0))
- {
- mac_timer = timerset (1000);
- while (CARRIER && !timeup (mac_timer))
- {
- if (TIMED_READ (0) == DC1)
- break;
-
- time_release ();
- }
- return (AC0);
- }
-
- /* Otherwise, fallthrough */
-
- default:
- break;
- }
- return (AC0);
- }
-
- int ACXMACK (XMARGSP args)
- {
- if (!args->options.SEAlink)
- ++(args->ACKBLK);
-
- return (AC0);
- }
-
- int ACXMNAK (XMARGSP args)
- {
- if (!args->options.SEAlink)
- {
- args->SendBLK = args->ACKBLK + 1;
- args->curr_byte = (args->SendBLK - 1) * 128L;
- if (args->curr_byte < 0L)
- args->curr_byte = 0L;
-
- if (args->SendBLK > 0)
- ++(args->tot_errs);
-
- Get_Block (args);
- }
-
- return (AC0);
- }
-
- int ACRESYNC (XMARGSP args)
- {
- CLEAR_OUTBOUND ();
- if (args->result != SUCCESS)
- {
- SENDBYTE (NAK);
- return (SUCCESS);
- }
-
- if (args->SendBLK == 1)
- {
- args->prev_bytes = (args->resync_block - 1) * 128;
- if (args->prev_bytes > args->filelen)
- args->prev_bytes = args->filelen;
- status_line (MSG_TXT(M_SYNCHRONIZING), args->prev_bytes);
- }
- else
- {
- ++(args->tot_errs);
- }
-
- args->options.SEAlink = 1;
- args->Window = calc_window ();
- args->SendBLK = args->resync_block;
- args->curr_byte = (args->SendBLK - 1) * 128L;
- if (args->curr_byte < 0L)
- args->curr_byte = 0L;
-
- Get_Block (args);
- args->ACKBLK = args->SendBLK - 1;
- SENDBYTE (ACK);
- return (SUCCESS);
- }
-
-
- void Check_ACKNAK (XMARGSP args)
- {
- (void) state_machine (ACKNAK_Check, args, AC0);
- }
-
- int Receive_Resync (long *resync_block)
- {
- unsigned char resyncit[30];
- unsigned char *p;
- unsigned char a, b;
- unsigned int nak_crc, his_crc;
-
- p = resyncit;
-
- while ((*p = (unsigned char) TIMED_READ(1)) != ETX)
- {
- if ((*p < '0') || (*p > '9'))
- {
- status_line (">SEAlink Send: Resync bad byte '%02x'", *p);
- return (RESYNC_ERR);
- }
- ++p;
- }
- *p = '\0';
- nak_crc = crc_block ((unsigned char *) resyncit, (int) strlen ((char *) resyncit));
- a = (unsigned char) TIMED_READ (1);
- b = (unsigned char) TIMED_READ (1);
- his_crc = (b << 8) | a;
-
- if (nak_crc != his_crc)
- {
- status_line (">SEAlink Send: Resync bad crc %04x/%04x", nak_crc, his_crc);
- return (CRC_ERR);
- }
-
- *resync_block = atol ((char *) resyncit);
-
- status_line (">SEAlink Send: Resync to %ld", *resync_block);
- return (SUCCESS);
- }
-
- int calc_window ()
- {
- int window;
-
- window = (int) (cur_baud.rate_value / 400);
- if (window <= 0)
- window = 2;
- if (small_window)
- window = (window > 6) ? 6 : window;
-
- return (window);
- }
-