📄 tftpc.c
字号:
*
* Note: None
********************************************************************/
TFTP_RESULT TFTPIsPutReady(void)
{
WORD_VAL opCode;
WORD_VAL blockNumber;
BOOL bTimeOut;
// Check to see if timeout has occurred.
bTimeOut = FALSE;
if ( TickGetDiff(TickGet(), _tftpStartTick) >= TFTP_GET_TIMEOUT_VAL )
{
bTimeOut = TRUE;
_tftpStartTick = TickGet();
}
switch(_tftpState)
{
case SM_TFTP_WAIT_FOR_ACK:
// When timeout occurs in this state, application must retry.
if ( bTimeOut )
{
if ( _tftpRetries++ > (TFTP_MAX_RETRIES-1) )
{
DEBUG(printf("TFTPIsPutReady(): Timeout.\n"));
// Forget about all previous attempts.
_tftpRetries = 1;
return TFTP_TIMEOUT;
}
else
{
DEBUG(printf("TFTPIsPutReady(): Retry.\n"));
return TFTP_RETRY;
}
}
// Must wait for ACK from server before we transmit next block.
if ( !UDPIsGetReady(_tftpSocket) )
break;
// Get opCode.
UDPGet(&opCode.byte.MSB);
UDPGet(&opCode.byte.LSB);
// Get block number.
UDPGet(&blockNumber.byte.MSB);
UDPGet(&blockNumber.byte.LSB);
// Discard everything else.
UDPDiscard();
// This must be ACK or else there is a problem.
if ( opCode.Val == TFTP_OPCODE_ACK )
{
// Also the block number must match with what we are expecting.
if ( MutExVar.group2._tftpBlockNumber.Val == blockNumber.Val )
{
// Mark that block we sent previously has been ack'ed.
_tftpFlags.bits.bIsAcked = TRUE;
// Since we have ack, forget about previous retry count.
_tftpRetries = 1;
// If this file is being closed, this must be last ack.
// Declare it as closed.
if ( _tftpFlags.bits.bIsClosing )
{
_tftpFlags.bits.bIsClosed = TRUE;
return TFTP_OK;
}
// Or else, wait for put to become ready so that caller
// can transfer more data blocks.
_tftpState = SM_TFTP_WAIT;
}
else
{
DEBUG(printf("TFTPIsPutReady(): "\
"Unexpected block %d received - droping it...\n", \
blockNumber.Val));
return TFTP_NOT_READY;
}
}
else if ( opCode.Val == TFTP_OPCODE_ERROR )
{
// For error opCode, remember error code so that application
// can read it later.
_tftpError = blockNumber.Val;
// Declare error.
return TFTP_ERROR;
}
else
break;
case SM_TFTP_WAIT:
// Wait for UDP is to be ready to transmit.
if ( UDPIsPutReady(_tftpSocket) )
{
// Put next block of data.
MutExVar.group2._tftpBlockNumber.Val++;
UDPPut(0);
UDPPut(TFTP_OPCODE_DATA);
UDPPut(MutExVar.group2._tftpBlockNumber.byte.MSB);
UDPPut(MutExVar.group2._tftpBlockNumber.byte.LSB);
// Remember that this block is not yet flushed.
_tftpFlags.bits.bIsFlushed = FALSE;
// Remember that this block is not acknowledged.
_tftpFlags.bits.bIsAcked = FALSE;
// Now, TFTP module is ready to put more data.
_tftpState = SM_TFTP_READY;
return TFTP_OK;
}
break;
case SM_TFTP_READY:
// TFTP module is said to be ready only when underlying UDP
// is ready to transmit.
if ( UDPIsPutReady(_tftpSocket) )
return TFTP_OK;
}
return TFTP_NOT_READY;
}
/*********************************************************************
* Function: void TFTPPut(BYTE c)
*
* PreCondition: TFTPOpenFile() is called with TFTP_FILE_MODE_WRITE
* and TFTPIsPutReady() = TRUE
*
* Input: c - Data byte that is to be written
*
* Output: None
*
* Side Effects: None
*
* Overview: Puts given data byte into TFTP socket.
* If end of data block is reached, it
* transmits entire block.
*
* Note: Use this function to write file to server.
********************************************************************/
void TFTPPut(BYTE c)
{
// Put given byte directly to UDP
UDPPut(c);
// One more byte in data block.
++MutExVar.group2._tftpBlockLength.Val;
// Check to see if data block is full.
if ( MutExVar.group2._tftpBlockLength.byte.MSB == TFTP_BLOCK_SIZE_MSB )
{
// If it is, then transmit this block.
UDPFlush();
// Remember that current block is already flushed.
_tftpFlags.bits.bIsFlushed = TRUE;
// Prepare for next block.
MutExVar.group2._tftpBlockLength.Val = 0;
// Need to wait for ACK from server before putting
// next block of data.
_tftpState = SM_TFTP_WAIT_FOR_ACK;
}
}
static void _TFTPSendFileName(TFTP_OPCODE opcode, char *fileName)
{
BYTE c;
// Write opCode
UDPPut(0);
UDPPut(opcode);
// write file name, including NULL.
do
{
c = *fileName++;
UDPPut(c);
} while ( c != '\0' );
// Write mode - always use octet or binay mode to transmit files.
UDPPut('o');
UDPPut('c');
UDPPut('t');
UDPPut('e');
UDPPut('t');
UDPPut(0);
// Transmit it.
UDPFlush();
// Reset data block length.
MutExVar.group2._tftpBlockLength.Val = 0;
}
static void _TFTPSendAck(WORD_VAL blockNumber)
{
// Write opCode.
UDPPut(0);
UDPPut(TFTP_OPCODE_ACK);
// Write block number for this ack.
UDPPut(blockNumber.byte.MSB);
UDPPut(blockNumber.byte.LSB);
// Transmit it.
UDPFlush();
}
TFTP_RESULT TFTP_Connect(IP_ADDR *ServerIP)
{
TFTP_RESULT TFTPc_Result;
unsigned int cnt = 0;
TFTPOpen( ServerIP );
delay( 2 );
do
{
StackTask();
TFTPc_Result = TFTPIsOpened();
switch( TFTPc_Result )
{
case TFTP_TIMEOUT:
// retry five times to connect,user can change the value.
if( cnt<5 )
{
TFTPOpen( ServerIP );
cnt++;
delay( 2 );
break;
}
else
return TFTP_ERROR;
case TFTP_NOT_READY:
break;
}
} while ( TFTPc_Result != TFTP_OK );
print1("\nSuccess to setup a connection with remote server !\n");
return TFTP_OK;
}
TFTP_RESULT TFTP_Operate(char* fileName, TFTP_FILE_MODE operateMode, BYTE* buff, unsigned int length)
{
unsigned int cnt = 0;
TFTP_RESULT TFTPc_Result;
BYTE* tempBuff;
tempBuff = buff;
TFTPOpenFile(fileName, operateMode);
delay( 10 );
// check if the file has been opened and
// using an active socket to read the file's content
do
{
StackTask();
TFTPc_Result = TFTPIsFileOpened();
switch( TFTPc_Result )
{
case TFTP_TIMEOUT:
case TFTP_RETRY:
// timeout five times to abord and return TFTP_ERROR
if ( cnt<5 )
{
TFTPOpenFile(fileName, operateMode);
cnt++;
delay( 10 );
break;
}
else
return TFTP_ERROR;
case TFTP_NOT_READY:
case TFTP_OK:
break;
}
} while ( TFTPc_Result != TFTP_OK );
/* debug info ouput to the PC through the UART **************/
switch(operateMode)
{
case TFTP_FILE_MODE_READ:
print1("\nRead request to server is successful !\n");
break ;
case TFTP_FILE_MODE_WRITE:
print1("\nWrite request to server is successful !\n");
break;
}
/************************************************************/
switch( operateMode )
{
case TFTP_FILE_MODE_READ:
do
{
*buff = TFTPGet();
if( buff > (tempBuff+length) )
break;
else
buff++;
} while( (TFTPIsGetReady() != TFTP_END_OF_FILE) );
print1("\nReading data is finished,the next to close the connection !\n");
// close the connetion
TFTPCloseFile();
TFTPClose();
print1("\nTFTP connect is successful closed !\n");
break;
case TFTP_FILE_MODE_WRITE:
cnt = 0;
do
{
tempBuff = *buff;
TFTPPut( tempBuff );
buff++;
cnt++;
} while( cnt < length );
print1("\nWriting data is finished,the next to close the connection !\n");
// close the connetion
TFTPCloseFile();
// delay(100);
do
{
StackTask();
TFTPc_Result = TFTPIsFileClosed();
switch( TFTPc_Result )
{
case TFTP_TIMEOUT:
case TFTP_ERROR:
print1("\nTFTPIsPutReady(): Timeout or Error\n");
return TFTP_ERROR;
case TFTP_RETRY:
case TFTP_NOT_READY:
print1("\nTFTPIsPutReady(): Retry or Not_Ready\n");
TFTPCloseFile();
break;
}
} while( TFTPc_Result != TFTP_OK );
TFTPClose();
print1("\nTFTP connect is successful closed !\n");
break;
default:
print1("\nTFTP connect is successful closed !\n");
}
return TFTP_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -