📄 tptx.c
字号:
/*
TPTX.C
(c) 1996 by Oliver Kraus
*/
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <assert.h>
#include <dos.h>
#include <fcntl.h>
#include "tptx.h"
#include "crc16.h"
#include "crc32.h"
#include "cio.h"
/* #include "debugmem.h" */
#define TPTX_ID_STR "transmitter: "
char *tptx_es_ipx_not_found = TPTX_ID_STR "ipx not found";
char *tptx_es_socket_table_full = TPTX_ID_STR "socket table full";
char *tptx_es_socket_open = TPTX_ID_STR "socket already open";
char *tptx_es_out_of_memory = TPTX_ID_STR "out of memory";
/* - - - - - state prototypes - - - - - - - - - - - - - - - - - - - - - - */
void tptx_state_none(tptx_type tptx);
void tptx_state_gen_request(tptx_type tptx);
void tptx_state_chk_request(tptx_type tptx);
void tptx_state_wait_ack_request(tptx_type tptx);
void tptx_state_user_check(tptx_type tptx);
void tptx_state_gen_file_start(tptx_type tptx);
void tptx_state_chk_file_start(tptx_type tptx);
void tptx_state_wait_ack_file_start(tptx_type tptx);
void tptx_state_gen_block_start(tptx_type tptx);
void tptx_state_chk_block_start(tptx_type tptx);
void tptx_state_wait_ack_block_start(tptx_type tptx);
void tptx_state_gen_data(tptx_type tptx);
void tptx_state_chk_data(tptx_type tptx);
void tptx_state_gen_block_end(tptx_type tptx);
void tptx_state_chk_block_end(tptx_type tptx);
void tptx_state_wait_ack_block_end(tptx_type tptx);
void tptx_state_gen_file_end(tptx_type tptx);
void tptx_state_chk_file_end(tptx_type tptx);
void tptx_state_wait_ack_file_end(tptx_type tptx);
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
allocate pool memory
*/
int tptx_OpenPool(tptx_type tptx, size_t b_len, int b_cnt)
{
int i;
/* check against 16 bit system */
if ( (long)b_len*(long)b_cnt > 65500 )
return 1;
/* assign parameter */
tptx->b_len = b_len;
tptx->b_cnt = b_cnt;
tptx->tx_cnt = b_cnt+TPTX_TX_ADD;
tptx->b_pool_size = b_cnt*b_len;
/* data buffers for ipx listen process */
tptx->tx_data = (char **)malloc(tptx->tx_cnt*sizeof(char *));
if ( tptx->tx_data != NULL )
{
for( i = 0; i < tptx->tx_cnt; i++ )
tptx->tx_data[i] = (char *)malloc(tptx->b_len+TP_BLK_INFO_SIZE);
for( i = 0; i < tptx->tx_cnt; i++ )
if ( tptx->tx_data[i] == NULL )
break;
if ( i >= tptx->tx_cnt )
{
/* allocate ipx ecb data buffers */
tptx->tx_ecb = (ipx_ecb_struct **)malloc(tptx->tx_cnt*sizeof(ipx_ecb_struct *));
if ( tptx->tx_ecb != NULL )
{
for( i = 0; i < tptx->tx_cnt; i++ )
tptx->tx_ecb[i] = (ipx_ecb_struct *)malloc(sizeof(ipx_ecb_struct));
for( i = 0; i < tptx->tx_cnt; i++ )
if ( tptx->tx_ecb[i] == NULL )
break;
if ( i >= tptx->tx_cnt )
{
/* clear ecb buffers */
for( i = 0; i < tptx->tx_cnt; i++ )
{
tptx->tx_ecb[i]->inuse = 0;
tp_set_blk_id(tptx->tx_data[i], TP_ID_NONE);
}
/* allocate block send list */
tptx->b_list_ptr = (short *)malloc(tptx->b_cnt*sizeof(short));
if ( tptx->b_list_ptr != NULL )
{
/* allocate memory pool */
tptx->b_pool_ptr = (char *)malloc(tptx->b_pool_size);
if ( tptx->b_pool_ptr != NULL )
{
tptx->b_pool_dptr = (char *)malloc(tptx->b_pool_size);
if ( tptx->b_pool_dptr != NULL )
{
return 1;
}
free(tptx->b_pool_dptr);
tptx->b_pool_dptr = NULL;
}
/* deallocate everything, if something went wrong */
free(tptx->b_list_ptr);
tptx->b_list_ptr = NULL;
}
}
for( i = 0; i < tptx->tx_cnt; i++ )
if ( tptx->tx_ecb[i] != NULL )
free(tptx->tx_ecb[i]);
free(tptx->tx_ecb);
tptx->tx_ecb = NULL;
}
}
for( i = 0; i < tptx->tx_cnt; i++ )
if ( tptx->tx_data[i] != NULL )
free(tptx->tx_data[i]);
free(tptx->tx_data);
tptx->tx_data = NULL;
}
return 0;
}
int tptx_IsOk(tptx_type tptx)
{
assert(tptx != NULL);
assert(tptx->tx_cnt == tptx->b_cnt+TPTX_TX_ADD);
assert(tptx->b_cnt*2 < (int)tptx->b_len);
return 1;
}
tptx_type tptx_Open(unsigned short socket, int is_lfn)
{
tptx_type tptx;
if ( ipx_init() == 0 )
{
fprintf(stderr, tptx_es_ipx_not_found);
return NULL;
}
switch(ipx_open_socket(socket))
{
case 0x0fe:
fprintf(stderr, tptx_es_socket_table_full);
return NULL;
case 0x0ff:
fprintf(stderr, tptx_es_socket_open);
return NULL;
}
tptx = (tptx_type)malloc(sizeof(tptx_struct));
if ( tptx != NULL )
{
tptx->flags = 0;
if ( c_is_long_filename(0) != 0 && is_lfn != 0 )
tptx->flags |= TP_FLAG_IS_LFN;
tptx->socket = socket;
tptx->is_adr_known = 0;
tptx->f_name = NULL;
tptx->f_logname = NULL;
tptx->f_logsname = NULL;
tptx->fp = NULL;
/* tptx->f_handle = -1; */
tptx->small_delay = CLOCKS_PER_SEC/2;
tptx->large_delay = CLOCKS_PER_SEC*2;
/*
tptx->small_delay = 1;
tptx->large_delay = 2;
*/
tptx_SetState(tptx, tptx_state_none);
tptx->is_aux = 0;
tptx->f_time_sum = (clock_t)0;
tptx->f_len_sum = 0L;
if ( tptx_OpenPool(tptx, TPTX_B_LEN, TPTX_B_CNT) != 0 )
{
tptx->rx_data = (char *)malloc(tptx->b_len+TP_BLK_INFO_SIZE);
if ( tptx->rx_data != NULL )
{
tptx->rx_ecb = (ipx_ecb_struct *)malloc(sizeof(ipx_ecb_struct));
if ( tptx->rx_ecb != NULL )
{
tptx->rx_ecb->inuse = 0;
tptx->rx_ecb->cc = 0;
tp_set_blk_id(tptx->rx_data, TP_ID_NONE);
tptx_ListenECB(tptx);
return tptx;
}
free(tptx->rx_data);
}
tptx_ClosePool(tptx);
}
free(tptx);
}
ipx_close_socket(socket);
return NULL;
}
void tptx_ClosePool(tptx_type tptx)
{
int i;
assert(tptx != NULL);
free(tptx->b_pool_ptr);
tptx->b_pool_ptr = NULL;
free(tptx->b_pool_dptr);
tptx->b_pool_dptr = NULL;
free(tptx->b_list_ptr);
tptx->b_list_ptr = NULL;
for( i = 0; i < tptx->tx_cnt; i++ )
if ( tptx->tx_ecb[i] != NULL )
{
ipx_cancel_ecb(tptx->tx_ecb[i]);
free(tptx->tx_ecb[i]);
}
free(tptx->tx_ecb);
tptx->tx_ecb = NULL;
for( i = 0; i < tptx->tx_cnt; i++ )
if ( tptx->tx_data[i] != NULL )
free(tptx->tx_data[i]);
free(tptx->tx_data);
tptx->tx_data = NULL;
}
void tptx_CloseFile(tptx_type tptx)
{
/* if ( tptx->f_handle >= 0 ) */
if ( tptx->fp != NULL )
{
fclose(tptx->fp);
tptx->fp = NULL;
/* tptx->f_handle = -1; */
tptx->f_time_sum += clock()-tptx->f_start;
tptx->f_len_sum += tptx->f_len;
}
if ( tptx->f_name != NULL )
{
free(tptx->f_name);
tptx->f_name = NULL;
}
tptx->is_ended = 1;
}
int tptx_OpenFile(tptx_type tptx, char *name)
{
tptx_CloseFile(tptx);
tptx->f_len = 0L;
tptx->f_pos = 0L;
tptx->f_crc = 0UL;
tptx->f_d_crc = 0UL;
tptx->f_is_skip = 0;
tptx->f_start = clock();
tptx->b_is_dptr_ok = 0;
tptx->f_date = 0;
tptx->f_time = 0;
tptx->fp = NULL;
tptx->f_name = NULL;
if ( name != NULL )
{
tptx->f_name = (char *)malloc(strlen(name)+1);
if ( tptx->f_name == NULL )
return 0;
strcpy(tptx->f_name, name);
/* tptx->f_handle = c_open(name, O_RDONLY|O_BINARY, 0); */
tptx->fp = fopen(name, "rb");
if ( tptx->fp == NULL )
return 0;
fseek(tptx->fp, 0L, SEEK_END);
tptx->f_len = ftell( tptx->fp );
fseek(tptx->fp, 0L, SEEK_SET);
/* tptx->f_len = filelength(fileno(tptx->fp)); */
_dos_getfileattr( name, &(tptx->f_attr) );
{
int handle;
_dos_open( name, _O_RDONLY, &handle );
_dos_getftime( handle, &(tptx->f_date), &(tptx->f_time) );
_dos_close( handle );
}
}
tptx_SetState(tptx, tptx_state_gen_request);
tptx_ListenECB(tptx);
return 1;
}
void tptx_Close(tptx_type tptx)
{
assert(tptx != NULL);
if ( tptx->f_logname != NULL )
free(tptx->f_logname);
if ( tptx->f_logsname != NULL )
free(tptx->f_logsname);
tptx_CloseFile(tptx);
ipx_cancel_ecb(tptx->rx_ecb);
free(tptx->rx_ecb);
free(tptx->rx_data);
tptx_ClosePool(tptx);
ipx_close_socket(tptx->socket);
free(tptx);
}
void tptx_SetAux(tptx_type tptx, int (*aux)( int msg, void *data ))
{
if ( tptx_IsOk(tptx) == 0 )
return;
tptx->aux = aux;
tptx->is_aux = 1;
}
void tptx_DoAux(tptx_type tptx, int msg, void *data)
{
if ( tptx_IsOk(tptx) == 0 )
return;
if ( tptx->is_aux != 0 )
tptx->aux(msg, data);
}
void tptx_DoPAux(tptx_type tptx, int msg)
{
tptx->pdata.total = tptx->f_len;
tptx->pdata.curr = tptx->f_pos;
tptx->pdata.crc = tptx->f_crc;
tptx->pdata.path = tptx->f_name;
tptx->pdata.file_start = tptx->f_start;
tptx->pdata.missed = 0;
if ( tptx->pdata.path == NULL )
{
tptx->pdata.path = tptx->f_logsname;
}
tptx_DoAux(tptx, msg, (void *)&(tptx->pdata));
}
int tptx_Send(tptx_type tptx, char *phy_name, char *log_name, char *log_sname)
{
if ( tptx->f_logname != NULL )
{
free(tptx->f_logname);
tptx->f_logname = NULL;
}
if ( tptx->f_logsname != NULL )
{
free(tptx->f_logsname);
tptx->f_logsname = NULL;
}
tptx->f_logname = (char *)malloc(strlen(log_name)+1);
if ( tptx->f_logname == NULL )
return 0;
strcpy(tptx->f_logname, log_name);
if ( log_sname == NULL )
log_sname = log_name;
tptx->f_logsname = (char *)malloc(strlen(log_sname)+1);
if ( tptx->f_logsname == NULL )
return 0;
strcpy(tptx->f_logsname, log_sname);
if ( tptx_OpenFile(tptx, phy_name) == 0 )
return 0;
tptx->is_ended = 0;
return 1;
}
size_t tptx_GetExpectedReadSize(tptx_type tptx)
{
size_t elen;
if ( tptx->f_len-tptx->f_pos >= (long)tptx->b_pool_size )
elen = tptx->b_pool_size;
else
elen = (size_t)(tptx->f_len-tptx->f_pos);
return elen;
}
int tptx_Read(tptx_type tptx)
{
size_t len, i;
len = 0;
if ( tptx_IsOk(tptx) == 0 )
return 0;
if ( tptx->b_is_dptr_ok != 0 )
return 1;
if ( tptx->fp != NULL )
{
assert(tptx->f_pos == ftell(tptx->fp));
len = fread(tptx->b_pool_dptr, 1, tptx->b_pool_size, tptx->fp);
if (len != tptx_GetExpectedReadSize(tptx))
{
static char s[80];
sprintf(s, "read error at position %ld", tptx->f_pos);
tptx_Error(tptx, s);
return 0;
}
if ( (tptx->flags & TP_FLAG_IS_DISABLE_CRC) == 0 )
{
if ( (tptx->flags & TP_FLAG_IS_CRC32) == 0 )
{
for( i = 0; i < len; i += 1024 )
{
ipx_dispatch();
tptx->f_d_crc = (unsigned long)crc16((unsigned short)tptx->f_d_crc,
(unsigned char *)tptx->b_pool_dptr+(size_t)i,
(len > i+1024) ? 1024 : len-i);
}
}
else
{
for( i = 0; i < len; i += 1024 )
{
ipx_dispatch();
tptx->f_d_crc = crc32(tptx->f_d_crc,
(unsigned char *)tptx->b_pool_dptr+(size_t)i,
(len > i+1024) ? 1024 : len-i);
}
}
/*
tptx->f_d_crc = crc32(tptx->f_d_crc,
(unsigned char *)tptx->b_pool_dptr, len);
*/
}
}
tptx->f_read_len = (long)len;
tptx->b_is_dptr_ok = 1;
return 1;
}
int tptx_CopyRead(tptx_type tptx)
{
if ( tptx->b_is_dptr_ok == 0 )
{
if ( tptx_Read(tptx) == 0 )
return 0;
}
memcpy(tptx->b_pool_ptr, tptx->b_pool_dptr, tptx->f_read_len);
tptx->f_crc = tptx->f_d_crc;
tptx->f_pos += tptx->f_read_len;
tptx->b_is_dptr_ok = 0;
return 1;
}
void tptx_InitPool(tptx_type tptx, int b_curr_cnt, short *list)
{
int i;
tptx->b_curr_cnt = b_curr_cnt;
tptx->b_list_cnt = 0;
if ( list == NULL )
{
for( i = 0; i < b_curr_cnt; i++ )
tptx->b_list_ptr[i] = (short)i;
}
else
{
for( i = 0; i < b_curr_cnt; i++ )
tptx->b_list_ptr[i] = list[i];
}
}
void tptx_CopyMemoryFromPool(tptx_type tptx, int no, void *adr, size_t len)
{
assert(no < tptx->b_cnt);
memcpy(adr, tptx->b_pool_ptr+no*tptx->b_len, len);
}
void tptx_SendECB(tptx_type tptx, int no)
{
tp_set_blk_ver(tptx->tx_data[no], TP_VERSION);
if ( tptx->is_adr_known == 0 )
{
ipx_fill_send_ecb(
tptx->tx_ecb[no],
ipx_get_header(NULL, tptx->socket, tptx->socket),
tptx->tx_data[no],
tptx->b_len+TP_BLK_INFO_SIZE);
}
else
{
ipx_fill_send_ecb(
tptx->tx_ecb[no],
ipx_get_header(&(tptx->adr), tptx->socket, tptx->socket),
tptx->tx_data[no],
tptx->b_len+TP_BLK_INFO_SIZE);
}
if ( ipx_send_ecb(tptx->tx_ecb[no]) == 0 )
{
static char s[80];
sprintf(s, "cannot send msg %d", tp_get_blk_id(tptx->tx_data[no]) );
tptx_Error(tptx, s);
}
}
void tptx_Error(tptx_type tptx, char *s)
{
fprintf(stderr, "\n");
fprintf(stderr, TPTX_ID_STR "%s\n", s);
tptx->is_ended = 2;
tptx_SetState(tptx, tptx_state_none);
if ( tptx->is_adr_known != 0 )
{
clock_t c1 = clock() + CLOCKS_PER_SEC;
long cnt = 4L;
while ( clock() < c1 && cnt > 0L )
{
clock_t c2;
ipx_dispatch();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -