diff --git a/src/sbbs3/zmodem.c b/src/sbbs3/zmodem.c index af03e52cee058a182dca9e84c8bb2403e2587c4c..1a8e56856db2d49573f781ccb020bafab9060ac1 100644 --- a/src/sbbs3/zmodem.c +++ b/src/sbbs3/zmodem.c @@ -1323,6 +1323,7 @@ int zmodem_get_zfin(zmodem_t* zm) return 0; } + /* * send from the current position in the file * all the way to end of file or until something goes wrong. @@ -1352,8 +1353,6 @@ int zmodem_send_from(zmodem_t* zm, FILE* fp, ulong pos, ulong* sent) /* * read a block from the file */ - if(zm->block_size < 128 || zm->block_size > sizeof(zm->tx_data_subpacket)) - zm->block_size = 1024; /* sanity check block size here */ n = fread(zm->tx_data_subpacket,sizeof(BYTE),zm->block_size,fp); @@ -1367,7 +1366,7 @@ int zmodem_send_from(zmodem_t* zm, FILE* fp, ulong pos, ulong* sent) } #endif if(zm->progress!=NULL) - zm->progress(zm->cbdata, pos, ftell(fp)); + zm->progress(zm->cbdata, ftell(fp)); type = ZCRCG; @@ -1389,11 +1388,6 @@ int zmodem_send_from(zmodem_t* zm, FILE* fp, ulong pos, ulong* sent) if(zmodem_send_data(zm, type, zm->tx_data_subpacket, n)!=0) return(TIMEOUT); - if(sent!=NULL) - *sent+=n; - - buf_sent+=n; - if(type == ZCRCW || type == ZCRCE) { int ack; lprintf(zm,LOG_DEBUG,"Sent end-of-frame (%s sub-packet)", chr(type)); @@ -1420,7 +1414,6 @@ int zmodem_send_from(zmodem_t* zm, FILE* fp, ulong pos, ulong* sent) lprintf(zm,LOG_DEBUG,"zmodem_send_from: read error at offset %lu", ftell(fp) ); return ZACK; } - } /* @@ -1445,6 +1438,19 @@ int zmodem_send_from(zmodem_t* zm, FILE* fp, ulong pos, ulong* sent) if(zm->cancelled) return(-1); + if(sent!=NULL) + *sent+=n; + + buf_sent+=n; + + zm->consecutive_errors = 0; + + if(zm->block_size < zm->max_block_size) { + zm->block_size*=2; + if(zm->block_size > zm->max_block_size) + zm->block_size = zm->max_block_size; + } + if(type == ZCRCW) /* end-of-frame */ zmodem_send_pos_header(zm, ZDATA, ftell(fp), /* Hex? */ FALSE); } @@ -1477,6 +1483,21 @@ BOOL zmodem_send_file(zmodem_t* zm, char* fname, FILE* fp, BOOL request_init, ti int i; unsigned errors; + if(zm->block_size == 0) + zm->block_size = ZBLOCKLEN; + + if(zm->block_size < 128) + zm->block_size = 128; + + if(zm->block_size > sizeof(zm->tx_data_subpacket)) + zm->block_size = sizeof(zm->tx_data_subpacket); + + if(zm->max_block_size < zm->block_size) + zm->max_block_size = zm->block_size; + + if(zm->max_block_size > sizeof(zm->rx_data_subpacket)) + zm->max_block_size = sizeof(zm->rx_data_subpacket); + if(sent!=NULL) *sent=0; @@ -1624,27 +1645,19 @@ BOOL zmodem_send_file(zmodem_t* zm, char* fname, FILE* fp, BOOL request_init, ti } while(type != ZRPOS); - zm->transfer_start = time(NULL); + zm->transfer_start_time = time(NULL); + zm->transfer_start_pos = 0; + if(zm->rxd_header_pos && zm->rxd_header_pos <= zm->current_file_size) { + pos = zm->transfer_start_pos = zm->rxd_header_pos; + lprintf(zm,LOG_INFO,"Starting transfer at offset: %lu (resume)", pos); + } if(start!=NULL) - *start=zm->transfer_start; + *start=zm->transfer_start_time; rewind(fp); + zm->consecutive_errors = 0; do { - /* - * fetch pos from the ZRPOS header - */ - - if(type == ZRPOS) { - if(zm->rxd_header_pos <= zm->current_file_size) { - if(pos != zm->rxd_header_pos) { - pos = zm->rxd_header_pos; - lprintf(zm,LOG_INFO,"Resuming transfer from offset: %lu", pos); - } - } else - lprintf(zm,LOG_WARNING,"Invalid ZRPOS offset: %lu", zm->rxd_header_pos); - } - /* * and start sending */ @@ -1654,13 +1667,39 @@ BOOL zmodem_send_file(zmodem_t* zm, char* fname, FILE* fp, BOOL request_init, ti if(!is_connected(zm)) return(FALSE); + if(type == ZFERR || type == ZABORT || zm->cancelled) + return(FALSE); + if(sent!=NULL) *sent+=sent_bytes; - if(type == ZFERR || type == ZABORT || type == TIMEOUT || zm->cancelled) + if(type == ZACK) /* success */ + break; + + if(zm->block_size == zm->max_block_size && zm->max_block_size > ZBLOCKLEN) + zm->max_block_size /= 2; + + if(zm->block_size > 128) + zm->block_size /= 2; + + if(++zm->consecutive_errors > zm->max_errors) return(FALSE); - } while(type == ZRPOS || type == ZNAK); + /* + * fetch pos from the ZRPOS header + */ + + if(type == ZRPOS) { + if(zm->rxd_header_pos <= zm->current_file_size) { + if(pos != zm->rxd_header_pos) { + pos = zm->rxd_header_pos; + lprintf(zm,LOG_INFO,"Resuming transfer from offset: %lu", pos); + } + } else + lprintf(zm,LOG_WARNING,"Invalid ZRPOS offset: %lu", zm->rxd_header_pos); + } + + } while(type == ZRPOS || type == ZNAK || type==TIMEOUT); lprintf(zm,LOG_INFO,"Finishing transfer on rx of header type: %s", chr((uchar)type)); @@ -1775,7 +1814,7 @@ int zmodem_recv_files(zmodem_t* zm, const char* download_dir, ulong* bytes_recei lprintf(zm,LOG_WARNING,"Incomplete download (%ld bytes received, expected %lu)" ,l,bytes); } else { - if((t=time(NULL)-zm->transfer_start)<=0) + if((t=time(NULL)-zm->transfer_start_time)<=0) t=1; b=l-start_bytes; if((cps=b/t)==0) @@ -1898,7 +1937,8 @@ unsigned zmodem_recv_file_data(zmodem_t* zm, FILE* fp, ulong offset) int i=0; unsigned errors=0; - zm->transfer_start=time(NULL); + zm->transfer_start_pos=offset; + zm->transfer_start_time=time(NULL); fseek(fp,offset,SEEK_SET); offset=ftell(fp); @@ -1909,7 +1949,7 @@ unsigned zmodem_recv_file_data(zmodem_t* zm, FILE* fp, ulong offset) if(i!=ENDOFFRAME) zmodem_send_pos_header(zm, ZRPOS, ftell(fp), /* Hex? */ TRUE); - if((i = zmodem_recv_file_frame(zm,fp,offset)) == ZEOF) + if((i = zmodem_recv_file_frame(zm,fp)) == ZEOF) break; if(i!=ENDOFFRAME) { if(i>0) @@ -1921,7 +1961,7 @@ unsigned zmodem_recv_file_data(zmodem_t* zm, FILE* fp, ulong offset) } -int zmodem_recv_file_frame(zmodem_t* zm, FILE* fp, ulong offset) +int zmodem_recv_file_frame(zmodem_t* zm, FILE* fp) { unsigned n; int type; @@ -1957,8 +1997,11 @@ int zmodem_recv_file_frame(zmodem_t* zm, FILE* fp, ulong offset) fwrite(zm->rx_data_subpacket,1,n,fp); } + if(type==FRAMEOK) + zm->block_size = n; + if(zm->progress!=NULL) - zm->progress(zm->cbdata,offset,ftell(fp)); + zm->progress(zm->cbdata,ftell(fp)); if(zm->cancelled) return(ZCAN); @@ -1983,7 +2026,7 @@ char* zmodem_ver(char *buf) void zmodem_init(zmodem_t* zm, void* cbdata ,int (*lputs)(void*, int level, const char* str) - ,void (*progress)(void* unused, ulong, ulong) + ,void (*progress)(void* unused, ulong) ,int (*send_byte)(void*, uchar ch, unsigned timeout) ,int (*recv_byte)(void*, unsigned timeout) ,BOOL (*is_connected)(void*) @@ -1992,13 +2035,14 @@ void zmodem_init(zmodem_t* zm, void* cbdata memset(zm,0,sizeof(zmodem_t)); /* Use sane default values */ - zm->send_timeout=10; /* seconds */ - zm->recv_timeout=10; /* seconds */ + zm->send_timeout=15; /* seconds */ + zm->recv_timeout=15; /* seconds */ #if 0 zm->byte_timeout=3; /* seconds */ zm->ack_timeout=10; /* seconds */ #endif - zm->block_size=1024; + zm->block_size=ZBLOCKLEN; + zm->max_block_size=ZBLOCKLEN; zm->max_errors=9; zm->cbdata=cbdata; diff --git a/src/sbbs3/zmodem.h b/src/sbbs3/zmodem.h index d0beca76cb16db45a356ec2d5662b75f207e87a6..5d6d96d4da15cfaa85e9fe9263ea1b56928d8618 100644 --- a/src/sbbs3/zmodem.h +++ b/src/sbbs3/zmodem.h @@ -36,6 +36,8 @@ * zmodem constants */ +#define ZBLOCKLEN 1024 /* "true" Zmodem max subpacket length */ + #define ZMAXHLEN 0x10 /* maximum header information length */ #define ZMAXSPLEN 0x400 /* maximum subpacket length */ @@ -232,7 +234,8 @@ typedef struct { ulong total_bytes; unsigned files_remaining; unsigned bytes_remaining; - time_t transfer_start; + ulong transfer_start_pos; + time_t transfer_start_time; int receive_32bit_data; int use_crc16; @@ -259,13 +262,15 @@ typedef struct { unsigned recv_timeout; unsigned max_errors; unsigned block_size; + unsigned max_block_size; + unsigned consecutive_errors; /* Callbacks */ void* cbdata; int (*lputs)(void*, int level, const char* str); int (*send_byte)(void*, BYTE ch, unsigned timeout); int (*recv_byte)(void*, unsigned timeout); - void (*progress)(void*, ulong start_pos, ulong current_pos); + void (*progress)(void*, ulong current_pos); BOOL (*is_connected)(void*); BOOL (*data_waiting)(void*); @@ -273,7 +278,7 @@ typedef struct { void zmodem_init(zmodem_t*, void* cbdata ,int (*lputs)(void*, int level, const char* str) - ,void (*progress)(void*, ulong, ulong) + ,void (*progress)(void*, ulong current_pos) ,int (*send_byte)(void*, BYTE ch, unsigned timeout) ,int (*recv_byte)(void*, unsigned timeout) ,BOOL (*is_connected)(void*) @@ -299,7 +304,7 @@ BOOL zmodem_send_file(zmodem_t*, char* name, FILE* fp, BOOL request_init, time_ int zmodem_recv_files(zmodem_t* zm, const char* download_dir, ulong* bytes_received); int zmodem_recv_init(zmodem_t* zm); unsigned zmodem_recv_file_data(zmodem_t*, FILE*, ulong offset); -int zmodem_recv_file_frame(zmodem_t* zm, FILE* fp, ulong offset); +int zmodem_recv_file_frame(zmodem_t* zm, FILE* fp); int zmodem_recv_header_and_check(zmodem_t* zm); #endif