/* TPTX.C (c) 1996 by Oliver Kraus */ #include #include #include #include #include #include #include "tptx.h" #include "crc16.h" #include "crc32.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) { 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; tptx->socket = socket; tptx->is_adr_known = 0; tptx->f_name = NULL; tptx->f_logname = NULL; tptx->fp = NULL; tptx->small_delay = CLOCKS_PER_SEC/2; tptx->large_delay = CLOCKS_PER_SEC*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->fp != NULL ) { fclose(tptx->fp); tptx->fp = NULL; 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->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); 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; if ( tptx->pdata.path == NULL ) { tptx->pdata.path = tptx->f_logname; } tptx_DoAux(tptx, msg, (void *)&(tptx->pdata)); } int tptx_Send(tptx_type tptx, char *phy_name, char *log_name) { if ( tptx->f_logname != NULL ) { free(tptx->f_logname); tptx->f_logname = NULL; } tptx->f_logname = (char *)malloc(strlen(log_name)+1); if ( tptx->f_logname == NULL ) return 0; strcpy(tptx->f_logname, log_name); 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(); while ( tptx->tx_ecb[0]->inuse == 0 ) { tp_set_blk_id(tptx->tx_data[0], TP_ID_ERROR); tp_set_blk_ver(tptx->tx_data[0], TP_VERSION); strcpy(tp_get_blk_data_adr(tptx->tx_data[0]), s); ipx_fill_send_ecb( tptx->tx_ecb[0], ipx_get_header(&(tptx->adr), tptx->socket, tptx->socket), tptx->tx_data[0], tptx->b_len+TP_BLK_INFO_SIZE); ipx_send_ecb(tptx->tx_ecb[0]); cnt--; } c2 = clock() + CLOCKS_PER_SEC/8; while ( clock() < c2 ) ; } } } int tptx_ListenECB(tptx_type tptx) { if ( tptx->rx_ecb->inuse != 0 ) { return 1; } if ( ipx_fill_receive_ecb( tptx->rx_ecb, tptx->socket, tptx->rx_data, tptx->b_len+TP_BLK_INFO_SIZE) == NULL ) { tptx_Error(tptx, "cannot fill receive ecb"); return 0; } if ( ipx_listen_ecb(tptx->rx_ecb) == 0 ) { tptx_Error(tptx, "cannot listen to ecb"); return 0; } return 1; } int tptx_ListenAndSearch(tptx_type tptx, short id1, short id2) { if ( tptx->rx_ecb->inuse == 0 ) { /* printf("inuse: %d \r", tptx->rx_ecb->inuse); */ if ( tptx->rx_ecb->cc == 0 ) { if (tp_ecb_get_id(tptx->rx_ecb) == TP_ID_ERROR ) { static char s[80]; sprintf(s, "remote error: '%s'", tp_ecb_get_data_adr(tptx->rx_ecb)); tptx_Error(tptx, s); return 0; } if (tp_ecb_get_id(tptx->rx_ecb) != id1 && tp_ecb_get_id(tptx->rx_ecb) != id2 ) { if ( tptx_ListenECB(tptx) == 0 ) return 0; } else { return 1; } } else { printf(TPTX_ID_STR "receive warning: %s\n", ipx_get_ecb_cc_string(tptx->rx_ecb)); if ( tptx_ListenECB(tptx) == 0 ) return 0; } } return 0; } void tptx_WaitSend(tptx_type tptx, int no, void (*next_state)(tptx_type tptx), void (*repeated_state)(tptx_type tptx), clock_t delay) { if ( tptx->tx_ecb[no]->inuse == 0 ) { if ( tptx->tx_ecb[no]->cc != 0 ) { tptx_Error(tptx, ipx_get_ecb_cc_string(tptx->tx_ecb[0])); } else { tptx->clock_dest = clock()+delay; tptx_SetRepeatedState(tptx, repeated_state); tptx_SetState(tptx, next_state); } } } int tptx_CheckTime(tptx_type tptx) { if ( tptx->clock_dest < clock() ) { tptx_SetState(tptx, tptx_GetRepeatedState(tptx)); return 0; } return 1; } int tptx_Dispatch(tptx_type tptx) { ipx_dispatch(); if ( tptx->is_ended != 0 ) return tptx->is_ended; tptx->state_fn(tptx); if ( tptx->state_fn != tptx_state_user_check ) { if ( kbhit() != 0 ) { if ( getch() == 27 ) { tptx_Error(tptx, "user break"); } } } return tptx->is_ended; } /* - - - - - state functions - - - - - - - - - - - - - - - - - - - - - - - */ void tptx_state_none(tptx_type tptx) { tptx_ListenECB(tptx); } void tptx_state_gen_request(tptx_type tptx) { tp_request request; tp_debug_out("tptx_state_gen_request"); request = (tp_request)tp_get_blk_data_adr(tptx->tx_data[0]); request->adr = *ipx_get_local_net_number(); request->file_size = tptx->f_len; /* request->flags = 0; */ request->flags = tptx->flags; if ( tptx->f_name == NULL ) request->flags |= TP_FLAG_IS_DIR; request->attr = tptx->f_attr; request->time = tptx->f_time; request->date = tptx->f_date; strcpy( tp_get_blk_data_adr(tptx->tx_data[0])+sizeof(tp_request_struct), tptx->f_logname); tp_set_blk_id(tptx->tx_data[0], TP_ID_REQUEST); tptx_SendECB(tptx, 0); tptx_SetState(tptx, tptx_state_chk_request); } void tptx_state_chk_request(tptx_type tptx) { tp_debug_out("tptx_state_chk_request"); tptx_WaitSend(tptx, 0, tptx_state_wait_ack_request, tptx_state_gen_request, tptx->large_delay); } void tptx_state_wait_ack_request(tptx_type tptx) { /* tp_debug_out("tptx_state_wait_ack_request"); */ if ( tptx_CheckTime(tptx) == 0 ) return; if ( tptx_ListenAndSearch(tptx, TP_ID_ACK_REQUEST, TP_ID_NONE) != 0 ) { tp_ack_request ack_request; ack_request = (tp_ack_request)tp_ecb_get_data_adr(tptx->rx_ecb); tptx->adr = ack_request->adr; tptx->is_adr_known = 1; tptx_ListenECB(tptx); if ( ack_request->exist != 0 && (tptx->flags & TP_FLAG_IS_NO_USER_CHECK) == 0 ) { printf("remote file '%s' exists, overwrite (y,n,a)? ", tptx->f_logname); fflush(stdout); tptx_SetState(tptx, tptx_state_user_check); } else { tptx_DoPAux(tptx, TP_MSG_PSTART); tptx_SetState(tptx, tptx_state_gen_file_start); } } } void tptx_state_user_check(tptx_type tptx) { if ( kbhit() != 0 ) { int c = getch(); switch(c) { case 'n': case 'N': printf("%c\n", c); tptx->f_is_skip = 1; tptx_SetState(tptx, tptx_state_gen_file_end); return; case 'a': case 'A': printf("%c\n", c); tptx_SetFlag(tptx, TP_FLAG_IS_NO_USER_CHECK); tptx_DoPAux(tptx, TP_MSG_PSTART); tptx_SetState(tptx, tptx_state_gen_file_start); return; case 'y': case 'Y': case 'j': case 'J': printf("%c\n", c); tptx_DoPAux(tptx, TP_MSG_PSTART); tptx_SetState(tptx, tptx_state_gen_file_start); return; case 27: tptx_Error(tptx, "user escape"); return; } } if ( tptx_ListenAndSearch(tptx, TP_ID_FILE_START, TP_ID_NONE) != 0 ) { tp_file_start file_start; file_start = (tp_file_start)tp_get_blk_data_adr(tptx->rx_data); tptx->f_is_skip = file_start->is_skip_file; tptx->flags = file_start->flags; tptx_ListenECB(tptx); if ( tptx->f_is_skip != 0 ) { printf("n\n"); tptx_SetState(tptx, tptx_state_gen_file_end); } else { printf("y/a\n"); tptx_DoPAux(tptx, TP_MSG_PSTART); tptx_SetState(tptx, tptx_state_gen_file_start); } } } void tptx_state_gen_file_start(tptx_type tptx) { tp_file_start file_start; tp_debug_out("tptx_state_gen_file_start"); file_start = (tp_file_start)tp_get_blk_data_adr(tptx->tx_data[0]); file_start->is_skip_file = 0; file_start->flags = tptx->flags; tp_set_blk_id(tptx->tx_data[0], TP_ID_FILE_START); tptx_SendECB(tptx, 0); tptx_SetState(tptx, tptx_state_chk_file_start); } void tptx_state_chk_file_start(tptx_type tptx) { tp_debug_out("tptx_state_chk_file_start"); tptx_WaitSend(tptx, 0, tptx_state_wait_ack_file_start, tptx_state_gen_file_start, tptx->small_delay); } void tptx_state_wait_ack_file_start(tptx_type tptx) { /* tp_debug_out("tptx_state_wait_ack_file_start"); */ if ( tptx_CheckTime(tptx) == 0 ) return; if ( tptx_ListenAndSearch(tptx, TP_ID_ACK_FILE_START, TP_ID_NONE) != 0 ) { tptx->f_start = clock(); tptx_ListenECB(tptx); tptx_SetState(tptx, tptx_state_gen_block_start); } } void tptx_state_gen_block_start(tptx_type tptx) { tp_block_start block_start; tp_debug_out("tptx_state_gen_block_start"); /* printf("filepos: %ld\n", tptx->f_pos); */ tptx_DoPAux(tptx, TP_MSG_PDATA); block_start = (tp_block_start)tp_get_blk_data_adr(tptx->tx_data[0]); block_start->cnt = (tptx_GetExpectedReadSize(tptx)+tptx->b_len-1)/tptx->b_len; tp_set_blk_id(tptx->tx_data[0], TP_ID_BLOCK_START); tptx_SendECB(tptx, 0); tptx_SetState(tptx, tptx_state_chk_block_start); } void tptx_state_chk_block_start(tptx_type tptx) { tp_debug_out("tptx_state_chk_block_start"); tptx_WaitSend(tptx, 0, tptx_state_wait_ack_block_start, tptx_state_gen_block_start, tptx->small_delay); } void tptx_state_wait_ack_block_start(tptx_type tptx) { tp_debug_out("tptx_state_wait_ack_block_start"); if ( tptx_CheckTime(tptx) == 0 ) return; if ( tptx_ListenAndSearch(tptx, TP_ID_ACK_BLOCK_START, TP_ID_NONE) != 0 ) { tptx_ListenECB(tptx); tptx_CopyRead(tptx); tptx_InitPool(tptx, (tptx_GetExpectedReadSize(tptx)+tptx->b_len-1)/tptx->b_len, NULL); tptx_SetState(tptx, tptx_state_gen_data); } } void tptx_state_gen_data(tptx_type tptx) { /* tp_debug_out("tptx_state_gen_data"); */ if ( tptx->b_list_cnt < tptx->b_curr_cnt ) { tp_data data; /* printf("(%d,%d/%d)", (int)tptx->b_list_ptr[tptx->b_list_cnt], tptx->b_list_cnt, tptx->b_curr_cnt); */ data = (tp_data)tp_get_blk_data_adr(tptx->tx_data[tptx->b_list_cnt]); data->no = tptx->b_list_ptr[tptx->b_list_cnt]; if ( tptx->b_pool_size-(size_t)(((size_t)data->no)*tptx->b_len) < tptx->b_len ) data->len = tptx->b_pool_size-(size_t)(((size_t)data->no)*tptx->b_len); else data->len = tptx->b_len; tptx_CopyMemoryFromPool(tptx, data->no, tp_get_blk_data_adr(tptx->tx_data[tptx->b_list_cnt])+sizeof(tp_data_struct), data->len); tp_set_blk_id(tptx->tx_data[tptx->b_list_cnt], TP_ID_DATA); tptx_SendECB(tptx, tptx->b_list_cnt); tptx->b_list_cnt++; } else { tptx_SetState(tptx, tptx_state_chk_data); tptx_Read(tptx); } } void tptx_state_chk_data(tptx_type tptx) { int i, c; /* tp_debug_out("tptx_state_chk_data"); */ c = 0; for( i = 0; i < tptx->b_curr_cnt; i++ ) { if ( tptx->tx_ecb[i]->inuse == 0 ) { if ( tptx->tx_ecb[i]->cc != 0 ) { tptx_Error(tptx, ipx_get_ecb_cc_string(tptx->tx_ecb[0])); } else { c++; } } } if ( c == tptx->b_curr_cnt ) { tptx_SetState(tptx, tptx_state_gen_block_end); } } void tptx_state_gen_block_end(tptx_type tptx) { tp_block_end block_end; tp_debug_out("tptx_state_gen_block_end"); block_end = (tp_block_end)tp_get_blk_data_adr(tptx->tx_data[0]); block_end->crc = tptx->f_crc; tp_set_blk_id(tptx->tx_data[0], TP_ID_BLOCK_END); tptx_SendECB(tptx, 0); tptx_SetState(tptx, tptx_state_chk_block_end); } void tptx_state_chk_block_end(tptx_type tptx) { tp_debug_out("tptx_state_chk_block_end"); tptx_WaitSend(tptx, 0, tptx_state_wait_ack_block_end, tptx_state_gen_block_end, tptx->small_delay); } void tptx_state_wait_ack_block_end(tptx_type tptx) { /* tp_debug_out("tptx_state_wait_ack_block_end"); */ if ( tptx_CheckTime(tptx) == 0 ) return; if ( tptx_ListenAndSearch(tptx, TP_ID_ACK_BLOCK_END, TP_ID_MISSED_BLOCKS) != 0 ) { if ( tp_ecb_get_id(tptx->rx_ecb) == TP_ID_MISSED_BLOCKS ) { tp_missed_blocks missed_blocks; missed_blocks = (tp_missed_blocks)tp_ecb_get_data_adr(tptx->rx_ecb); /* printf("missed: %d\n", (int)missed_blocks->cnt); */ tptx_InitPool(tptx, missed_blocks->cnt, (short *)(tp_ecb_get_data_adr(tptx->rx_ecb)+ sizeof(tp_missed_blocks_struct))); tptx_SetState(tptx, tptx_state_gen_data); tptx_ListenECB(tptx); return; } else if ( tp_ecb_get_id(tptx->rx_ecb) == TP_ID_ACK_BLOCK_END ) { if ( tptx->f_pos == tptx->f_len ) { tptx_SetState(tptx, tptx_state_gen_file_end); } else { tptx_SetState(tptx, tptx_state_gen_block_start); } tptx_ListenECB(tptx); } } } void tptx_state_gen_file_end(tptx_type tptx) { tp_debug_out("tptx_state_gen_file_end"); tp_set_blk_id(tptx->tx_data[0], TP_ID_FILE_END); tptx_SendECB(tptx, 0); tptx_SetState(tptx, tptx_state_chk_file_end); } void tptx_state_chk_file_end(tptx_type tptx) { tp_debug_out("tptx_state_chk_file_end"); tptx_WaitSend(tptx, 0, tptx_state_wait_ack_file_end, tptx_state_gen_file_end, tptx->large_delay); } void tptx_state_wait_ack_file_end(tptx_type tptx) { tp_debug_out("tptx_state_wait_ack_file_end"); if ( tptx_CheckTime(tptx) == 0 ) return; if ( tptx_ListenAndSearch(tptx, TP_ID_ACK_FILE_END, TP_ID_NONE) != 0 ) { if ( tptx->f_is_skip == 0 ) { tptx_DoPAux(tptx, TP_MSG_PDATA); tptx_DoPAux(tptx, TP_MSG_PEND); } tptx_CloseFile(tptx); tptx_ListenECB(tptx); tptx_SetState(tptx, tptx_state_none); } }