📄 tftp.c
字号:
TFtpLinks[iLinkSlot].DestAddr.wPort = wSrcPort;
// Copy the data out of the temporary buffer
TFtpLinks[iLinkSlot].cwMsgLen = cwMsgLen;
TFtpLinks[iLinkSlot].wBlockNumber++;
memcpy( TFtpLinks[iLinkSlot].Buffer, pwMsg, cwMsgLen );
// Flip the state back to BUSY so that TFtpRead() can succeed.
TFtpLinks[iLinkSlot].State = TFTP_STATE_XFER_BUSY;
if (TFtpLinks[iLinkSlot].pfCallBack != NULL)
TFtpdCallBack( iLinkSlot, TFTPD_WRITE );
// Check to see if this is the last packet, if so we close
if (cwMsgLen != MAX_TFTP_DATA) {
TFtpLinks[iLinkSlot].State = TFTP_STATE_IDLE;
nNumTFtpLinksInUse--;
}
} else if (ntohs(*(pwMsg+1)) == TFtpLinks[iLinkSlot].wBlockNumber) {
// desktop lost the ACK for previous write, ack it again
UINT16 ack[2] = { htons(4), htons(TFtpLinks[iLinkSlot].wBlockNumber) };
BYTE buf[UDP_DATA_FRAME_OFFSET+sizeof(ack)];
EdbgOutputDebugString ("TFTP: Desktop losing ACK, block number = %d, Ack again\r\n",
TFtpLinks[iLinkSlot].wBlockNumber);
EbootSendUDP(buf, &(TFtpLinks[iLinkSlot].DestAddr), &(TFtpLinks[iLinkSlot].SrcAddr),
(LPBYTE) ack, sizeof (ack));
}
}
}
else {
// See if this is the acknowledge packet we've been waiting for
if (ntohs(*pwMsg) == 4 && ntohs(*(pwMsg+1)) == TFtpLinks[iLinkSlot].wBlockNumber) {
// Flip the state back to BUSY so that TFtpWrite() can succeed.
TFtpLinks[iLinkSlot].State = TFTP_STATE_XFER_BUSY;
if (TFtpLinks[iLinkSlot].pfCallBack != NULL)
TFtpdCallBack( iLinkSlot, TFTPD_READ );
// Check to see if this is the last packet, if so we close
if (TFtpLinks[iLinkSlot].cwMsgLen != MAX_TFTP_DATA)
TFtpLinks[iLinkSlot].State = TFTP_STATE_CLOSE;
}
}
break;
case TFTP_STATE_CLOSE:
// This was an O2HLink (Write), and we're just waiting for that last data packet to be acknowledged.
// If it has been, we'll close the link and go back to IDLE
if (ntohs(*pwMsg) == 4 && ntohs(*(pwMsg+1)) == TFtpLinks[iLinkSlot].wBlockNumber) {
TFtpLinks[iLinkSlot].State = TFTP_STATE_IDLE;
nNumTFtpLinksInUse--;
EdbgOutputDebugString( "TFtpStateMachine::TFTP_STATE_CLOSE Link Deleted\r\n" );
}
break;
} // switch(State)
}
// This routine will open a new link to the host. The DataDir parameter specifies if this is going to
// be a request to read (H2OLink) or write (O2HLink) data. The routine will return a non-zero link handle,
// which is actually the iLinkSlot+1, if there is a link slot available. Otherwise, it will return 0.
UINT16 TFtpOpen( EDBG_ADDR *pHostAddr, EDBG_ADDR *pMyAddr, char *pszFileName, TFtpLinkDir DataDir ) {
int i, iLinkSlot = (MAX_TFTP_LINKS - 1);
if (nNumTFtpLinksInUse >= MAX_TFTP_LINKS)
return 0;
if ((strlen(pszFileName) + 1) > MAX_TFTP_FILENAME) return 0;
// Find a link that isn't currently in use
for( i = 0; i < MAX_TFTP_LINKS; i++ ) {
if (TFtpLinks[i].State == TFTP_STATE_IDLE) {
iLinkSlot = i;
break;
}
}
TFtpLinks[iLinkSlot].DataDir = DataDir;
TFtpLinks[iLinkSlot].State = (DataDir == H2OLink) ? TFTP_STATE_XFER_WAIT : TFTP_STATE_OPEN;
TFtpLinks[iLinkSlot].pfCallBack = NULL;
strcpy( TFtpLinks[iLinkSlot].szFileName, pszFileName );
TFtpLinks[iLinkSlot].wBlockNumber = 0;
// Put in Read Request or Write Request as appropriate
*((UINT16*)(TFtpLinks[iLinkSlot].Buffer)) = htons((DataDir == H2OLink) ? 1 : 2);
TFtpLinks[iLinkSlot].cwMsgLen = 2;
// Put in the file name
strcpy( TFtpLinks[iLinkSlot].Buffer + 2, pszFileName );
TFtpLinks[iLinkSlot].cwMsgLen += strlen( pszFileName );
// Specify octet (binary) mode
strcpy( TFtpLinks[iLinkSlot].Buffer + TFtpLinks[iLinkSlot].cwMsgLen, "octet" );
TFtpLinks[iLinkSlot].cwMsgLen += 6;
// Send the read/write request packet back to the host
TFtpLinks[iLinkSlot].DestAddr = *pHostAddr;
TFtpLinks[iLinkSlot].DestAddr.wPort = wHostWellKnownServerPort;
TFtpLinks[iLinkSlot].SrcAddr = *pMyAddr;
TFtpLinks[iLinkSlot].SrcAddr.wPort = GenerateSrcPort();
EbootSendUDP(TFTPFrameBuffer, &(TFtpLinks[iLinkSlot].DestAddr), &(TFtpLinks[iLinkSlot].SrcAddr),
TFtpLinks[iLinkSlot].Buffer, TFtpLinks[iLinkSlot].cwMsgLen );
TFtpLinks[iLinkSlot].tLastTransmit = OEMEthGetSecs();
TFtpLinks[iLinkSlot].cwRetries = 0;
return iLinkSlot+1;
}
// This routine is called by a process that wants to read data from an existing link.
// The routine will return TFTP_WAIT if the read failed because no new data packet has arrived.
// A TFTP_ERROR will be returned if an error has occured and the link has been terminated
// It will return TFTP_SUCCESS if the read succeeded. The number of data bytes read indicates
// whether or not the link is closing. If the number of data bytes is 512, then more
// data is forthcoming. If the number of data bytes is < 512, then this is the last
// packet and the data link is now closed.
TFtpReturnCodes TFtpRead( UINT16 wLinkHandle, BYTE *pbData, UINT16 *cwDataLen ) {
UINT16 iLinkSlot;
iLinkSlot = wLinkHandle - 1;
// For the sake of speed, I will assume that the wLinkHandle is valid
if (TFtpLinks[iLinkSlot].State == TFTP_STATE_ERROR) {
EdbgOutputDebugString("!TftpReturnCodes, STATE_ERROR\n");
TFtpLinks[iLinkSlot].State = TFTP_STATE_IDLE;
nNumTFtpLinksInUse--;
return TFTP_ERROR;
}
else if (TFtpLinks[iLinkSlot].State == TFTP_STATE_XFER_BUSY) {
// Copy the data to the process' buffer
*cwDataLen = TFtpLinks[iLinkSlot].cwMsgLen - 4;
memcpy( TFtpLinks[iLinkSlot].Buffer + 4, pbData, *cwDataLen );
// Send an acknowlege packet back to the host
*((UINT16 *)TFtpLinks[iLinkSlot].Buffer) = htons(4);
*((UINT16 *)TFtpLinks[iLinkSlot].Buffer + 1) = htons(TFtpLinks[iLinkSlot].wBlockNumber);
TFtpLinks[iLinkSlot].cwMsgLen = 4;
EbootSendUDP(TFTPFrameBuffer, &(TFtpLinks[iLinkSlot].DestAddr), &(TFtpLinks[iLinkSlot].SrcAddr),
TFtpLinks[iLinkSlot].Buffer, TFtpLinks[iLinkSlot].cwMsgLen );
TFtpLinks[iLinkSlot].tLastTransmit = OEMEthGetSecs();
TFtpLinks[iLinkSlot].cwRetries = 0;
// I need to check to see if this is the last packet in the stream. If so, I
// need to close the link
if (TFtpLinks[iLinkSlot].cwMsgLen != MAX_TFTP_DATA) {
TFtpLinks[iLinkSlot].State = TFTP_STATE_IDLE;
nNumTFtpLinksInUse--;
}
// Otherwise, wait for the next data packet
else
TFtpLinks[iLinkSlot].State = TFTP_STATE_XFER_WAIT;
return TFTP_SUCCESS;
}
return TFTP_WAIT;
}
// This routine is called by a process that wants to write data to an existing link.
// The routine will return TFTP_WAIT if the write failed because the last data packet has not been
// acknowledged. A TFTP_ERROR will be returned if an error has occured and the link has been
// terminated. It will return TFTP_SUCCESS if the write succeeded. The number of data bytes written
// indicates whether or not the link is closing. If the number of data bytes is 512, then more
// data is forthcoming. If the number of data bytes is < 512, then this is the last
// packet and the data link is now closed.
TFtpReturnCodes TFtpWrite( UINT16 wLinkHandle, BYTE *pbData, UINT16 cwDataLen ) {
UINT16 iLinkSlot;
iLinkSlot = wLinkHandle - 1;
// For the sake of speed, I will assume that the wLinkHandle is valid
if (TFtpLinks[iLinkSlot].State == TFTP_STATE_ERROR) {
EdbgOutputDebugString("!!!! TFTP Errror\n");
TFtpLinks[iLinkSlot].State = TFTP_STATE_IDLE;
nNumTFtpLinksInUse--;
return TFTP_ERROR;
}
else if (TFtpLinks[iLinkSlot].State == TFTP_STATE_XFER_BUSY) {
// Send a new data packet to the host
*((UINT16 *)TFtpLinks[iLinkSlot].Buffer) = htons(3);
TFtpLinks[iLinkSlot].wBlockNumber++;
*((UINT16 *)TFtpLinks[iLinkSlot].Buffer + 1) = htons(TFtpLinks[iLinkSlot].wBlockNumber);
memcpy( TFtpLinks[iLinkSlot].Buffer + 4, pbData, cwDataLen );
TFtpLinks[iLinkSlot].cwMsgLen = cwDataLen + 4;
EbootSendUDP(TFTPFrameBuffer, &(TFtpLinks[iLinkSlot].DestAddr), &(TFtpLinks[iLinkSlot].SrcAddr),
TFtpLinks[iLinkSlot].Buffer, TFtpLinks[iLinkSlot].cwMsgLen );
TFtpLinks[iLinkSlot].tLastTransmit = OEMEthGetSecs();
TFtpLinks[iLinkSlot].cwRetries = 0;
// I need to check to see if this is the last packet in the stream. If so, I
// need go to TFTP_STATE_CLOSE so that we can wait for the last acknowledge packet.
if (TFtpLinks[iLinkSlot].cwMsgLen != MAX_TFTP_DATA)
TFtpLinks[iLinkSlot].State = TFTP_STATE_CLOSE;
// Otherwise, wait for the next acknowledge packet
else
TFtpLinks[iLinkSlot].State = TFTP_STATE_XFER_WAIT;
return TFTP_SUCCESS;
}
return TFTP_WAIT;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -