/* Comm WXMODEM send routines */ #define WXMDMSEND 1 #include "globals.h" #include extern void emit_tx_protocol(), emit_vw(), emits_rx(); extern void send_proto(), do_crc(); extern int read_proto(); static int naks, errsect; static ULONG bytes; static UBYTE sent, acked; static ULONG lastacked, nak_blk, ack_blk; WXMODEM_Send_File(file) UBYTE *file; { ULONG temp; int status, errcnt, eof = FALSE; int ch; naks = errsect = bytes = lastacked = acked = sent = errcnt = 0; while(!abort && (errcnt < RETRYMAX) ) { do { top: sprintf(sbuff,"File: %s bytes= %ld naks= %d [ %d ]\r", file, bytes, naks, errsect); status_line(0,sbuff); if((status = fillbuf()) == ERROR) { abortsend(); return FALSE; } if(status == FALSE) eof = TRUE; else { if(sendwsector() == ABORT) { abortsend(); return FALSE; } sent = sector & 3; sector++; } if((ch = getresponse()) != FALSE) { if(ch == NAK) { errcnt++; naks++; emits_rx(" NAK received\n"); nak_blk += 4; temp = (nak_blk - (lastacked & 3)) & 3; sector = (unsigned)(lastacked + temp); temp = (ULONG)SECSIZ * (ULONG)(sector - 1); if(lseek(fd,temp,0) == -1) { emits_rx(" File position error!\n"); abortsend(); return FALSE; } errsect = sector; goto top; } else if(ch == ACK) { errcnt = 0; ack_blk += 4; temp = (ack_blk - (lastacked & 3)) & 3; if(temp == 0) temp = 4; lastacked += temp; bytes += (SECSIZ * temp); } else if(ch == CAN) { send_proto(ACK); emits_rx(" Received cancel request\n"); close(fd); return TRUE; } } /* sprintf(sbuff,"File: %s bytes= %ld naks= %d [ %d ]\r", file, bytes, naks, errsect); status_line(0,sbuff); */ } while ( acked != sent ); if(eof) { endfile(); close(fd); return TRUE; } errcnt++; lseek(fd,(long)(-SECSIZ),1); sector--; Delay(250L); } abortsend(); return FALSE; } /************************************** sendwsector() transmits a single sector ***************************************/ sendwsector( ) { int i; cancel = FALSE; Process_window_event(); if( cancel || abort ) return ABORT; sprintf(sbuff,"\rTransmitting block %d",sector); emits_rx(sbuff); send_proto(SYN); send_proto(SYN); send_proto(SYN); send_wproto( SOH ); /* start of block */ send_wproto( sector ); /* sector number */ send_wproto( ~sector ); /* compliment of sector number */ crc = 0; /* clear CRC */ for( i = 0 ; i < SECSIZ ; i++ ) { if(xbuffer[ i ] == '\n' && asciiflg) xbuffer[ i ] = '\r'; wsendchar(xbuffer[ i ]); do_crc( xbuffer[ i ] ); if(viewflg) emit_vw( xbuffer[ i ] ); } do_crc(0); do_crc(0); /* cycle CRC generator */ wsendchar( crc >> 8 ); /* High byte */ wsendchar( crc ); /* Low byte */ } send_wproto(ch) UBYTE ch; { emit_tx_protocol(ch); wsendchar(ch); } wsendchar(ch) UBYTE ch; { switch(ch) { case SYN: case DLE: case XON: case XOFF: sendchar(DLE); sendchar( ch ^ 64); break; default: sendchar(ch); } } getresponse() { int ch; while(check_line()) { ch = read_proto(10,0); switch(ch) { case XOFF: do { ch = read_proto(10,0); } while( ch != XON && ch != TIMEOUT); return FALSE; case XON: return FALSE; case ACK: ch = read_proto(10,0); if(ch & ~3) return FALSE; ack_blk = acked = ch; return ACK; case NAK: ch = read_proto(10,0); if(ch & ~3) return FALSE; nak_blk = (ch & 3); return NAK; case CAN: ch = read_proto(10,0); if(ch == CAN) return CAN; } } return FALSE; } endfile() { int ch, errs = 0; do { send_proto(EOT); ch = read_proto(5,0); if(ch == TIMEOUT) errs++; } while(ch != ACK && errs < 3); } abortsend() { int ch, errs = 0; emits_rx("\nAborting transfer\n"); send_proto(CAN); send_proto(CAN); do { ch = read_proto(4); if(ch == CAN) { if(read_proto(4) == CAN) break; } if(ch == TIMEOUT) { send_proto(CAN); send_proto(CAN); errs++; } } while (errs < 3); send_proto(ACK); }