Skip to content
Snippets Groups Projects
Commit 11f1dd93 authored by rswindell's avatar rswindell
Browse files

Added block size adjustment during sends (and configurable "max_block_size").

Simplified progress callback even more with zm.start_transfer_pos member.
Added consecutive error counter.
Increased default send/recv timeouts from 10 to 15 seconds.
parent d5bc8d10
No related branches found
No related tags found
No related merge requests found
......@@ -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;
......
......@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment