0
mirror of https://github.com/Indemsys/Frequency_Inverter.git synced 2026-05-09 14:12:58 +00:00
Files
2022-01-04 12:22:53 +02:00

741 lines
22 KiB
C

/**HEADER********************************************************************
*
* Copyright (c) 2008 Freescale Semiconductor;
* All Rights Reserved
*
* Copyright (c) 2004-2008 Embedded Access Inc.;
* All Rights Reserved
*
* Copyright (c) 1989-2008 ARC International;
* All Rights Reserved
*
***************************************************************************
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: tftpsrv.c$
* $Version : 3.8.12.0$
* $Date : Jun-14-2012$
*
* Comments:
*
* This file contains the TFTP server implementation.
*
*END************************************************************************/
#include <rtcs.h>
#include "rtcs_prv.h"
#if RTCSCFG_ENABLE_UDP
#include <string.h>
#include <fio.h>
#include "tftp.h"
_rtcs_taskid TFTPSRV_task_id = 0;
#ifdef __MQX__
void TFTPSRV_Exit_handler(void);
#endif
void TFTPSRV_task(pointer, pointer);
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TFTPSRV_init
* Returned Value : error code
* Comments : Start the TFTP server
*
*END*-----------------------------------------------------------------*/
uint_32 TFTPSRV_init
(
char_ptr name,
uint_32 priority,
uint_32 stacksize
)
{ /* Body */
if (TFTPSRV_task_id == 0) {
return RTCS_task_create(name, priority, stacksize, TFTPSRV_task, NULL);
} else {
return RTCSERR_SERVER_ALREADY_RUNNING;
}
} /* Endbody */
/*TASK*-----------------------------------------------------------------
*
* Function Name : TFTPSRV_task
* Returned Value : void
* Comments : This task waits on port 69 for read and write
* requests, as well as servicing TFTP transactions
* already in progress.
*
*END*-----------------------------------------------------------------*/
void TFTPSRV_task
(
pointer dummy,
pointer creator
)
{ /* Body */
TFTPSRV_STATE_STRUCT_PTR tftpsrv_ptr;
sockaddr_in laddr;
uint_32 i, numtrans, timeout;
uint_32 error;
tftpsrv_ptr = RTCS_mem_alloc_zero(sizeof(TFTPSRV_STATE_STRUCT));
if (tftpsrv_ptr == NULL) {
RTCS_task_exit(creator, RTCSERR_OUT_OF_MEMORY);
} /* Endif */
TFTPSRV_task_id = RTCS_task_getid();
#ifdef __MQX__
/* Set up exit handler and context so that we can clean up if the TFTP Server is terminated */
_task_set_environment( _task_get_id(), (pointer) tftpsrv_ptr );
_task_set_exit_handler( _task_get_id(), TFTPSRV_Exit_handler );
#endif
tftpsrv_ptr->SRV_SOCK = socket(PF_INET, SOCK_DGRAM, 0);
if (tftpsrv_ptr->SRV_SOCK == RTCS_SOCKET_ERROR) {
RTCS_task_exit(creator, RTCSERR_OUT_OF_SOCKETS);
} /* Endif */
laddr.sin_family = AF_INET;
laddr.sin_port = IPPORT_TFTP;
laddr.sin_addr.s_addr = INADDR_ANY;
error = bind(tftpsrv_ptr->SRV_SOCK, (const sockaddr *)&laddr, sizeof(laddr));
if (error != RTCS_OK) {
RTCS_task_exit(creator, error);
} /* Endif */
RTCS_task_resume_creator(creator, RTCS_OK);
for (;;) {
timeout = TFTPSRV_service_timer(tftpsrv_ptr);
numtrans = tftpsrv_ptr->NUM_TRANSACTIONS;
error = RTCS_selectset(&tftpsrv_ptr->SRV_SOCK, numtrans+1, timeout);
if ((error == RTCS_OK) || (error == RTCS_SOCKET_ERROR)) {
continue;
} /* Endif */
if (error == tftpsrv_ptr->SRV_SOCK) {
/* New request, service it */
TFTPSRV_service_request(tftpsrv_ptr);
} else {
for (i = 0; i < numtrans; i++) {
if (error == tftpsrv_ptr->SOCKETS[i]) {
TFTPSRV_service_transaction(tftpsrv_ptr, tftpsrv_ptr->TRANS_PTRS[i]);
break;
} /* Endif */
} /* Endfor */
} /* Endif */
} /* Endfor */
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TFTPSRV_service_request
* Returned Value : void
* Comments : This function takes an initial TFTP request and
* starts the transaction process.
*
*END*-----------------------------------------------------------------*/
void TFTPSRV_service_request
(
TFTPSRV_STATE_STRUCT_PTR tftpsrv_ptr
/* [IN/OUT] The TFTP Server state */
)
{ /* Body */
TFTP_TRANS_STRUCT_PTR trans_ptr;
sockaddr_in sockaddr_t;
int_32 pkt_len, i;
uint_32 error;
char_ptr filename, filemode;
uint_16 sockaddrlen, pkt_op;
/* receive the datagram */
sockaddrlen = sizeof(sockaddr_t);
pkt_len = recvfrom(tftpsrv_ptr->SRV_SOCK, tftpsrv_ptr->BUFFER,
TFTP_MAX_MESSAGE_SIZE, 0, (sockaddr *)&sockaddr_t, &sockaddrlen);
if (pkt_len == RTCS_ERROR) {
return;
} /* Endif */
/* limit the number of concurrent transactions */
if (tftpsrv_ptr->NUM_TRANSACTIONS >= TFTPSRV_MAX_TRANSACTIONS) {
TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_busy, sockaddr_t);
return;
} /* Endif */
/* parse the request; extract op, filename and filemode */
i = 2;
filename = (char_ptr)tftpsrv_ptr->BUFFER + i;
for (; i<pkt_len; i++) {
if (tftpsrv_ptr->BUFFER[i] == '\0') break;
} /* Endfor */
i++;
filemode = (char_ptr)tftpsrv_ptr->BUFFER + i;
for (; i<pkt_len; i++) {
if (tftpsrv_ptr->BUFFER[i] == '\0') break;
} /* Endfor */
if (i >= pkt_len) {
TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_op, sockaddr_t);
return;
} /* Endif */
pkt_op = ntohs(tftpsrv_ptr->BUFFER);
/* allocate state for the new transaction */
trans_ptr = RTCS_mem_alloc_zero(sizeof(TFTP_TRANS_STRUCT));
if (trans_ptr == NULL) {
TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
return;
} /* Endif */
_mem_set_type(trans_ptr, MEM_TYPE_TFTP_TRANS_STRUCT);
/* validate the requested operation */
switch (pkt_op) {
case TFTPOP_RRQ:
trans_ptr->RECV_OP = TFTPOP_ACK;
trans_ptr->SEND_OP = TFTPOP_DATA;
break;
case TFTPOP_WRQ:
trans_ptr->RECV_OP = TFTPOP_DATA;
trans_ptr->SEND_OP = TFTPOP_ACK;
break;
default:
TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_op, sockaddr_t);
_mem_free(trans_ptr);
return;
} /* Endswitch */
/* open the requested file */
error = TFTPSRV_open_device(pkt_op, filename, filemode, &trans_ptr->TRANS_FILE_PTR);
if (error) {
switch (error) {
case RTCS_EACCES:
TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_accvio, sockaddr_t);
break;
case RTCS_ENOENT:
TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_nofile, sockaddr_t);
break;
case RTCS_EEXIST:
TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_exists, sockaddr_t);
break;
default:
TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
break;
} /* Endswitch */
_mem_free(trans_ptr);
return;
} /* Endif */
/* create a socket for the new transaction */
trans_ptr->SOCK = socket(PF_INET, SOCK_DGRAM, 0);
if (trans_ptr->SOCK == RTCS_SOCKET_ERROR) {
TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
RTCS_io_close(trans_ptr->TRANS_FILE_PTR);
_mem_free(trans_ptr);
return;
} /* Endif */
trans_ptr->ADDR.sin_family = sockaddr_t.sin_family;
trans_ptr->ADDR.sin_port = sockaddr_t.sin_port;
trans_ptr->ADDR.sin_addr.s_addr = sockaddr_t.sin_addr.s_addr;
sockaddr_t.sin_family = AF_INET;
sockaddr_t.sin_port = 0;
sockaddr_t.sin_addr.s_addr = INADDR_ANY;
error = bind(trans_ptr->SOCK, (const sockaddr *)&sockaddr_t, sizeof(sockaddr_t));
if (error != RTCS_OK) {
TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
shutdown(trans_ptr->SOCK, 0);
RTCS_io_close(trans_ptr->TRANS_FILE_PTR);
_mem_free(trans_ptr);
return;
} /* Endif */
/* build the first packet */
trans_ptr->BLOCK = 0;
switch (trans_ptr->SEND_OP) {
case TFTPOP_DATA:
TFTPSRV_build_DATA(trans_ptr);
break;
case TFTPOP_ACK:
TFTPSRV_build_ACK(trans_ptr);
trans_ptr->EXIT = FALSE;
break;
} /* Endswitch */
if (trans_ptr->SEND_SIZE < sizeof(TFTP_HEADER)) {
TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_srv, sockaddr_t);
shutdown(trans_ptr->SOCK, 0);
RTCS_io_close(trans_ptr->TRANS_FILE_PTR);
_mem_free(trans_ptr);
return;
} /* Endif */
/* send the first packet */
TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, TFTP_timeout_init(&trans_ptr->XMIT_TIMER));
TFTPSRV_send(trans_ptr);
tftpsrv_ptr->SOCKETS[tftpsrv_ptr->NUM_TRANSACTIONS] = trans_ptr->SOCK;
tftpsrv_ptr->TRANS_PTRS[tftpsrv_ptr->NUM_TRANSACTIONS] = trans_ptr;
tftpsrv_ptr->NUM_TRANSACTIONS++;
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TFTPSRV_open_device
* Returned Value : error code
* Comments : This function opens the requested device, if possible.
*
*END*-----------------------------------------------------------------*/
uint_32 TFTPSRV_open_device
(
uint_32 pkt_op,
/* [IN] the transaction type */
char_ptr filename,
/* [IN] the requested file */
char_ptr filemode,
/* [IN] the transfer mode */
MQX_FILE_PTR _PTR_ fd_ptr
/* [OUT] the open file descriptor */
)
{ /* Body */
char_ptr open_mode;
uint_32 error;
if (strcmp(filemode, "netascii") == 0) {
if (pkt_op == TFTPOP_RRQ) {
open_mode = "r";
} else {
open_mode = "w";
} /* Endif */
} else if (strcmp(filemode, "octet") == 0) {
if (pkt_op == TFTPOP_RRQ) {
open_mode = "rb";
} else {
open_mode = "wb";
} /* Endif */
} else {
return RTCS_EACCES;
} /* Endif */
if (!TFTPSRV_access(filename, pkt_op)) {
return RTCS_EACCES;
} /* Endif */
*fd_ptr = RTCS_io_open(filename, open_mode, &error);
return error;
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TFTPSRV_service_transaction
* Returned Value : void
* Comments : This function services a transaction in progress
* which has just received a packet.
*
*END*-----------------------------------------------------------------*/
void TFTPSRV_service_transaction
(
TFTPSRV_STATE_STRUCT_PTR tftpsrv_ptr,
/* [IN/OUT] The TFTP Server state */
TFTP_TRANS_STRUCT_PTR trans_ptr
/* [IN/OUT] The transaction state */
)
{ /* Body */
sockaddr_in sockaddr_tftp;
uint_32 block_num;
int_32 pkt_len, write_len;
uint_16 sockaddrlen, pkt_op;
/* receive the datagram */
sockaddrlen = sizeof(sockaddr_tftp);
pkt_len = recvfrom(trans_ptr->SOCK, tftpsrv_ptr->BUFFER,
TFTP_MAX_MESSAGE_SIZE, 0,(sockaddr *)&sockaddr_tftp, &sockaddrlen);
if (pkt_len == RTCS_ERROR) {
return;
} /* Endif */
/* verify the sender's address and port */
if ((trans_ptr->ADDR.sin_port != sockaddr_tftp.sin_port) ||
(trans_ptr->ADDR.sin_addr.s_addr != sockaddr_tftp.sin_addr.s_addr)) {
TFTP_SEND(tftpsrv_ptr->SRV_SOCK, _tftp_error_tid, sockaddr_tftp);
return;
} /* Endif */
/* get op and block number */
if (pkt_len < sizeof(TFTP_HEADER)) {
TFTP_SEND(trans_ptr->SOCK, _tftp_error_tid, sockaddr_tftp);
return;
} /* Endif */
pkt_op = ntohs(tftpsrv_ptr->BUFFER);
block_num = ntohs(tftpsrv_ptr->BUFFER + 2);
/* verify the requested operation */
if (pkt_op != trans_ptr->RECV_OP) {
if (pkt_op != TFTPOP_ERROR) {
TFTP_SEND(trans_ptr->SOCK, _tftp_error_op, sockaddr_tftp);
} /* Endif */
TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
return;
} /* Endif */
switch (pkt_op) {
case TFTPOP_DATA:
/* We are servicing a write request from a TFTP Client here */
if (block_num == trans_ptr->BLOCK) {
pkt_len -= sizeof(TFTP_HEADER);
write_len = RTCS_io_write(trans_ptr->TRANS_FILE_PTR,
tftpsrv_ptr->BUFFER + sizeof(TFTP_HEADER),
pkt_len);
if (write_len != pkt_len) {
TFTP_SEND(trans_ptr->SOCK, _tftp_error_srv, trans_ptr->ADDR);
TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
return;
} /* Endif */
TFTPSRV_build_ACK(trans_ptr);
trans_ptr->EXIT = (write_len < sizeof(TFTP_PACKET) - sizeof(TFTP_HEADER));
TFTPSRV_timer_cancel(tftpsrv_ptr, trans_ptr);
TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, TFTP_timeout_update(&trans_ptr->XMIT_TIMER));
TFTPSRV_send(trans_ptr);
} else if (block_num == trans_ptr->BLOCK - 1) {
TFTPSRV_timer_cancel(tftpsrv_ptr, trans_ptr);
TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, TFTP_timeout_restart(&trans_ptr->XMIT_TIMER));
TFTPSRV_send(trans_ptr);
} /* Endif */
break;
case TFTPOP_ACK:
/* We are servicing a read request */
if (block_num == trans_ptr->BLOCK) {
if (trans_ptr->EXIT) {
/* We've received the last ACK, exit */
TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
return;
} /* Endif */
TFTPSRV_build_DATA(trans_ptr);
if (trans_ptr->SEND_SIZE < sizeof(TFTP_HEADER)) {
TFTP_SEND(trans_ptr->SOCK, _tftp_error_srv, sockaddr_tftp);
TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
return;
} /* Endif */
TFTPSRV_timer_cancel(tftpsrv_ptr, trans_ptr);
TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, TFTP_timeout_update(&trans_ptr->XMIT_TIMER));
TFTPSRV_send(trans_ptr);
} /* Endif */
break;
} /* Endswitch */
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TFTPSRV_build_ACK
* Returned Value : void
* Comments : This function builds an ACK packet for client
* write requests.
*
*END*-----------------------------------------------------------------*/
void TFTPSRV_build_ACK
(
TFTP_TRANS_STRUCT_PTR trans_ptr
/* [IN/OUT] The transaction state */
)
{ /* Body */
htons(trans_ptr->SND.HEAD.OP, trans_ptr->SEND_OP);
htons(trans_ptr->SND.HEAD.BLOCK, trans_ptr->BLOCK);
trans_ptr->BLOCK++;
trans_ptr->SEND_SIZE = sizeof(TFTP_HEADER);
trans_ptr->NUM_RETRIES = 0;
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TFTPSRV_build_DATA
* Returned Value : void
* Comments : This function builds a DATA packet for client
* read requests.
*
*END*-----------------------------------------------------------------*/
void TFTPSRV_build_DATA
(
TFTP_TRANS_STRUCT_PTR trans_ptr
/* [IN/OUT] The transaction state */
)
{ /* Body */
int_32 datalen;
datalen = RTCS_io_read(trans_ptr->TRANS_FILE_PTR, (char_ptr)trans_ptr->SND.DATA, TFTP_DATA_SIZE);
if (datalen < 0) {
datalen = 0;
} /* Endif */
trans_ptr->BLOCK++;
htons(trans_ptr->SND.HEAD.OP, trans_ptr->SEND_OP);
htons(trans_ptr->SND.HEAD.BLOCK, trans_ptr->BLOCK);
trans_ptr->SEND_SIZE = sizeof(TFTP_HEADER) + datalen;
trans_ptr->NUM_RETRIES = 0;
trans_ptr->EXIT = (trans_ptr->SEND_SIZE < sizeof(TFTP_PACKET));
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TFTPSRV_send
* Returned Value : void
* Comments : This function (re)sends a packet.
*
*END*-----------------------------------------------------------------*/
void TFTPSRV_send
(
TFTP_TRANS_STRUCT_PTR trans_ptr
/* [IN/OUT] The transaction state */
)
{ /* Body */
sendto(trans_ptr->SOCK, &trans_ptr->SND, trans_ptr->SEND_SIZE, 0,
(sockaddr *)(&trans_ptr->ADDR), sizeof(trans_ptr->ADDR));
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TFTPSRV_timer_start
* Returned Value : void
* Comments : This function starts the retransmission timer.
*
*END*-----------------------------------------------------------------*/
void TFTPSRV_timer_start
(
TFTPSRV_STATE_STRUCT_PTR tftpsrv_ptr,
/* [IN/OUT] The TFTP Server state */
TFTP_TRANS_STRUCT_PTR trans_ptr,
/* [IN/OUT] The transaction state */
uint_32 timeout
/* [IN] The retransmission timeout */
)
{ /* Body */
TFTP_TRANS_STRUCT_PTR _PTR_ search_ptr;
trans_ptr->TIME = timeout;
for (search_ptr = &tftpsrv_ptr->EVENT_HEAD;;
search_ptr = &(*search_ptr)->NEXT) {
if (*search_ptr == NULL) {
/* Append to tail of list */
RTCS_DLIST_INS(*search_ptr, trans_ptr);
break;
} /* Endif */
if ((*search_ptr)->TIME > trans_ptr->TIME) {
/* Insert in middle (or head) of list */
(*search_ptr)->TIME -= trans_ptr->TIME;
RTCS_DLIST_INS(*search_ptr, trans_ptr);
break;
} /* Endif */
trans_ptr->TIME -= (*search_ptr)->TIME;
} /* Endfor */
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TFTPSRV_timer_cancel
* Returned Value : void
* Comments : This function stops the retransmission timer.
*
*END*-----------------------------------------------------------------*/
void TFTPSRV_timer_cancel
(
TFTPSRV_STATE_STRUCT_PTR tftpsrv_ptr,
/* [IN/OUT] The TFTP Server state */
TFTP_TRANS_STRUCT_PTR trans_ptr
/* [IN/OUT] The transaction state */
)
{ /* Body */
RTCS_DLIST_DEL(&tftpsrv_ptr->EVENT_HEAD, trans_ptr);
if (trans_ptr->NEXT) {
trans_ptr->NEXT->TIME += trans_ptr->TIME;
} /* Endif */
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TFTPSRV_service_timer
* Returned Value : time until the first transaction expiry in
* milliseconds, 0 if no pending transactions.
* Comments : This retransmits the last packet for all expired
* transactions. The transaction list is sorted by
* expiry time, so we can stop when the head of the list
* is unexpired.
*
*END*-----------------------------------------------------------------*/
uint_32 TFTPSRV_service_timer
(
TFTPSRV_STATE_STRUCT_PTR tftpsrv_ptr
/* [IN/OUT] The TFTP Server state */
)
{ /* Body */
TFTP_TRANS_STRUCT_PTR trans_ptr;
uint_32 time;
boolean expired;
while (tftpsrv_ptr->EVENT_HEAD) {
trans_ptr = tftpsrv_ptr->EVENT_HEAD;
time = TFTP_timeout_left(&trans_ptr->XMIT_TIMER, &expired);
if (!expired) {
trans_ptr->TIME = time;
return time;
} /* Endif */
RTCS_DLIST_DEL(tftpsrv_ptr->EVENT_HEAD, trans_ptr);
if (trans_ptr->EXIT) {
TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
continue;
} /* Endif */
#if TFTPSRV_TIMEOUT_RETRIES != TFTPSRV_INFINITE_RETRIES
if (++trans_ptr->NUM_RETRIES > TFTPSRV_TIMEOUT_RETRIES) {
TFTP_SEND(trans_ptr->SOCK, _tftp_error_to, trans_ptr->ADDR);
TFTPSRV_close_transaction(tftpsrv_ptr, trans_ptr);
continue;
} /* Endif */
#endif
TFTPSRV_send(trans_ptr);
TFTPSRV_timer_start(tftpsrv_ptr, trans_ptr, time);
} /* Endwhile */
/* Nothing in the event queue */
return 0;
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TFTPSRV_close_transaction
* Returned Value : void
* Comments : This function closes a transaction.
*
*END*-----------------------------------------------------------------*/
void TFTPSRV_close_transaction
(
TFTPSRV_STATE_STRUCT_PTR tftpsrv_ptr,
/* [IN/OUT] The TFTP Server state */
TFTP_TRANS_STRUCT_PTR trans_ptr
/* [IN/OUT] The transaction state */
)
{ /* Body */
uint_32 i;
TFTPSRV_timer_cancel(tftpsrv_ptr, trans_ptr);
for (i = 0; i < tftpsrv_ptr->NUM_TRANSACTIONS; i++) {
if (tftpsrv_ptr->TRANS_PTRS[i] == trans_ptr) {
break;
} /* Endif */
} /* Endfor */
RTCS_io_close(trans_ptr->TRANS_FILE_PTR);
shutdown(trans_ptr->SOCK, 0);
if (--tftpsrv_ptr->NUM_TRANSACTIONS) {
tftpsrv_ptr->TRANS_PTRS[i] = tftpsrv_ptr->TRANS_PTRS[tftpsrv_ptr->NUM_TRANSACTIONS];
tftpsrv_ptr->SOCKETS[i] = tftpsrv_ptr->SOCKETS[tftpsrv_ptr->NUM_TRANSACTIONS];
} /* Endif */
_mem_free(trans_ptr);
} /* Endbody */
#ifdef __MQX__
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TFTPSRV_stop
* Returned Value : error code
* Comments : Start the TFTPSRV task.
*
*END*-----------------------------------------------------------------*/
uint_32 TFTPSRV_stop( void )
{ /* Body */
if (TFTPSRV_task_id == 0) {
return RTCSERR_SERVER_NOT_RUNNING;
}
RTCS_task_abort(TFTPSRV_task_id);
TFTPSRV_task_id = 0;
return RTCS_OK;
} /* Endbody */
/*FUNCTION*-------------------------------------------------------------
*
* Function Name : TFTPSRV_Exit_handler
* Returned Value : error code
* Comments : Start the TFTPSRV task.
*
*END*-----------------------------------------------------------------*/
void TFTPSRV_Exit_handler( void )
{ /* Body */
TFTPSRV_STATE_STRUCT_PTR tftpsrv_ptr;
tftpsrv_ptr = (TFTPSRV_STATE_STRUCT_PTR) _task_get_environment( _task_get_id() );
if (tftpsrv_ptr != NULL) {
while (tftpsrv_ptr->NUM_TRANSACTIONS) {
TFTPSRV_close_transaction(tftpsrv_ptr,tftpsrv_ptr->EVENT_HEAD );
}
if (tftpsrv_ptr->SRV_SOCK) {
shutdown(tftpsrv_ptr->SRV_SOCK, 0);
tftpsrv_ptr->SRV_SOCK = 0;
}
}
TFTPSRV_task_id = 0;
} /* Endbody */
#endif
#endif
/* EOF */