⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tftpudp.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
字号:
/* tftpudp.c

   Copyright 1998 by InterNiche Technologies, Inc. All rights reserved.
   Copyright 1996 by NetPort Software.

   UDP API (Sockets or lightweight) dependant portion of the TFTP code.

*/

#include "tftpport.h"
#include "tftp.h"

#undef ip_addr

#include "q.h"         /* get netport IP stack defines */
#include "netbuf.h"
#include "net.h"
#include "ip.h"
#include "udp.h"


UDPCONN tftp_conn;

static int tftp_upcall(PACKET pkt, void * data);

/* tftp_udplisten() - Start a UDP listen on fhost & portS passed. This
is used by the tftp code to establish a receive endpoint prior
to sending UDP datagrams. If lport is 0 a useable value is obtained
from the UDP layer.

   The "ptr" parameter is callback data -  will be tfconn ptr for 
client, TFTPSERVER for server

Returns connection ID (socket or UDPCONN) if successful, else 
returns NULL if not.
*/

void *
tftp_udplisten(ip_addr fhost, unshort fport, unshort * lport, void * ptr)
{
UDPCONN u;
unshort tmpport;  /* tmp holder for local port value */

   /* first, get a local port for use on this connection */
   if(*lport == 0)   /* caller wants us to allocate one */
      tmpport = udp_socket();
   else  /* use port passed */
      tmpport = *lport;

   if(ptr == NULL)
      ptr = TFTPSERVER;  /* indicate server */

   u = udp_open(fhost, fport, tmpport, tftp_upcall, (void *)ptr);

   if(u)
   {
      *lport = tmpport;    /* return local port to caller */
      return((void*)u);    /* success */
   }
   else
      return NULL;      /* error */
}


/* tftp_udp_send(long conn, char * outbuf, int outlen);

Send a udp datagram to the connection indicated. Buffer with UDP data
to send and a length are passed. 

Retuns 0 if OK, else nonzero error.
*/

int
tftp_udpsend(struct tfconn * conn, void * outbuf, int outlen)
{
PACKET pkt;
int e;   /* error holder */

   pkt = (PACKET)conn->tf_outbuf.udp_use;

   /* sanity check buffer pointer */
   if((char *)outbuf != pkt->nb_prot)
   {
      /* this is OK on retrys, but not initial sends */
      if(((char *)outbuf <= pkt->nb_buff) ||  /* null outbuf == bad */
         (conn->tf_tmo == 0)) /* this is not a retry */
      {
         dtrap("tftpudp 1\n");
         return ENP_LOGIC;
      }
   }

   pkt->nb_prot = (char*)outbuf;
   pkt->nb_plen = outlen;
   pkt->fhost = conn->tf_fhost;
   pkt->net = NULL;  /* force it to route */

#ifdef ZEROCOPY_API  /* packet can be marked in use, not freed */
   pkt->inuse = 2;   /* clone it so it won't pk_free() on send */
#else    /* need to copy data in case we have to retry */
{
PACKET pkt2;   /* packet to send & free */
   pkt2 = udp_alloc(outlen, 0);
   if(!pkt2)
      return ENP_NOBUFFER;
   pkt2->nb_plen = pkt->nb_plen;
   pkt2->fhost = pkt->fhost;
   pkt2->net = NULL;
   MEMCPY(pkt2->nb_prot, pkt->nb_prot, outlen);
   pkt = pkt2; /* send duplicate pkt, keep original in tf_conn */
}
#endif

   e = udp_send(conn->tf_fport, conn->tf_lport, pkt);

   if(e < 0)
   {
      dtrap("tftpudp 2\n");
      return -1;
   }
   else
      return 0;
}

/* tftp_upcall() - UDP callback: handle received tftp requests. */

int
tftp_upcall(PACKET pkt, void * data)
{
   struct tfconn * cn;
   struct udp * pup;
   int err;

   /* get pointer to UDP header */
   pup = (struct udp *)pkt->nb_prot;
   pup -= 1;

   /* Find tftp session this packet is for. */
   if(data == TFTPSERVER) /* packet to our tftp server connection */
   {
#ifdef TFTP_SERVER
      /* call server for new session here */
      err = tfshnd(pkt->fhost, pup->ud_srcp, pkt->nb_prot);
#endif /* TFTP_SERVER */
      udp_free(pkt);
      return 0; /* do not return an error to the udp layer */
   }
   else
   {
      cn = (struct tfconn *)data;
      if(cn->tf_fhost != pkt->fhost)   /* sanity check */
      {
         dtrap("tftpudp 3\n");
         return ENP_NOT_MINE;
      }
   }

   if(cn->tf_inbuf.udp_use)
   {
      dtrap("tftpudp 4\n"); /* ever happen? */
   }

   cn->tf_inbuf.data = pkt->nb_prot;
   cn->tf_inbuf.dlen = pkt->nb_plen;
   cn->tf_inbuf.udp_use = (void*)pkt;

   tftprcv(cn, pup->ud_srcp);

   if(cn->tf_inbuf.udp_use) /* pkt may be freed in upcall */
   {
      udp_free(pkt);
      cn->tf_inbuf.udp_use = NULL;
   }

   return 0;
}

/* tftp_udpbuffer() - Called by tftp to ask udp layer for a packet buffer.
the data is filled into the passed cn->tf_outbuf if a buffer is obtained,
else everything in tf_outbuf is cleared.

The lightweight API grabs a buffer from the UDP layer to avoid doing a 
data copy. Sockets will probably need to calloc.....
*/

void
tftp_udpbuffer(struct tfconn * cn, int size)
{
PACKET pkt;

   if(cn->tf_outbuf.udp_use)
   {
      pkt = (PACKET)cn->tf_outbuf.udp_use;
      if(pkt->nb_plen >= (unsigned)size)
      {
         /* recycle existing buffer */
         pkt->nb_prot = (char*)cn->tf_outbuf.data;
         return;
      }
      else
      {
         udp_free(pkt);  /* old packet was too small */
      }
   }

   pkt = udp_alloc(size, 0);
   if(!pkt) /* alloc failed, clear outbuf pointers */
   {
      cn->tf_outbuf.data = NULL;
      cn->tf_outbuf.dlen = 0;
      cn->tf_outbuf.udp_use = NULL;
      return;
   }
   else  /* return buffer pointer */
   {
      cn->tf_outbuf.data = pkt->nb_prot;
      cn->tf_outbuf.dlen =  size;
      cn->tf_outbuf.udp_use = (void*)pkt;   /* so we can find struct later */
   }
}

/* tftp_udpfree() - called to free the udp buffer after it has been 
acked. 
*/

void
tftp_udpfree(struct tfconn * cn)
{
PACKET pkt;

   pkt = (PACKET)cn->tf_outbuf.udp_use;
#ifdef ZEROCOPY_API
   pkt->inuse = 1;   /* free this copy - "unclone" it */
#endif
   udp_free(pkt);
   cn->tf_outbuf.udp_use = NULL;
   cn->tf_outbuf.data = NULL;
}



int
tftp_udpclose(void* conn)
{
UDPCONN cn = (UDPCONN)conn;

   udp_close(cn);
   return 0;   /* no ability to detect error on this API */
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -