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

📄 tcpapi.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 2 页
字号:
    * after the tp is cleaned up
    */
   so->state |= SS_NOFDREF; 

   /* set state so that tcp_output() does the desired close */
   if((so->so_options & SO_LINGER) && (so->linger == 0))
   {
      /* application has explicitly set the socket to have a linger time 
       * of zero, which is how BSD let applications support TCP resets.
       * Support this here:
       */
      so_flush(so);                    /* flush socket data queues */
      tp->t_state = TCPS_CLOSED;   /* set up to send reset */
   }
   else     /* adjust the state for normal shutdown */
   {
      switch(tp->t_state)
      {
      case TCPS_ESTABLISHED:
      case TCPS_SYN_RECEIVED:
         tp->t_state = TCPS_FIN_WAIT_1;
         break;
      case TCPS_LISTEN:
      case TCPS_SYN_SENT:
         tp->t_state = TCPS_CLOSED;    /* this will force tp deletion below */
         break;
      case TCPS_CLOSE_WAIT:
         tp->t_state = TCPS_LAST_ACK;
         break;
      default:
         dtrap("tcpapi 0\n");    /* other states shouldn't happen */
         break;
      }
   }

   if (tp->t_template)
      tcp_output(tp);        /* send final data then FIN, or RST */

   if (tp && (tp->t_state == TCPS_CLOSED))
   {
      m_tcpclose(tp);
      tp=NULL;
   }
   /* if close was forced (LINGER & longer == 0) or tp was closed in tcp_output()
    * (e.g. we sent a reset packet) then delete socket now 
    */
   if (tp == NULL)
      m_delsocket(so);

rtn:
   UNLOCK_NET_RESOURCE(NET_RESID);

   return e;
}


/* FUNCTION: tcp_pktalloc()
 *
 * Allcate a packet for sending tcp data. when returned, pkt->nb_prot
 * points to a buffer big enough for the data size passed.
 *
 * PARAM1: size of TCP data for packet, limited to MTU - header size
 *
 * RETURNS: pointer to a packet, or NULL if a big enough packet was not
 * available.
 */

PACKET
tcp_pktalloc(int datasize)
{
   PACKET   pkt;
   int      headersize = 40 + MaxLnh;

   LOCK_NET_RESOURCE(FREEQ_RESID);
   pkt = pk_alloc(datasize + headersize);
   UNLOCK_NET_RESOURCE(FREEQ_RESID);
   if(!pkt)
      return NULL;

   /* default nb_prot starts after tcp header */
   pkt->nb_prot = pkt->nb_buff + headersize;
   pkt->nb_plen = pkt->m_len = 0;   /* no data in new packet */
   pkt->m_data = pkt->nb_prot;      /* assume tcp data will start at nb_prot */
   pkt->m_next = NULL;

   return pkt;
}


/* FUNCTION: tcp_pktfree()
 *
 * tcp_pktfree(PACKET p) - free a packet allocated by (presumably) 
 * tcp_pktalloc(). This is a simple wrapper around pk_free() to lock 
 * and unlock the free-queue resource. 
 *
 * 
 * PARAM1: PACKET p
 *
 * RETURNS: 
 */

void
tcp_pktfree(PACKET p)
{
   LOCK_NET_RESOURCE(FREEQ_RESID);
   pk_free(p);
   UNLOCK_NET_RESOURCE(FREEQ_RESID);
}


#ifdef BSDISH_SEND

/* FUNCTION: m_send()
 *
 * A workalike for the BSD sockets send() call
 *
 * PARAM1: M_SOCK socket,
 * PARAM2: char * buffer
 * PARAM3: unsigned length
 *
 * RETURNS: number of bytes actually sent, or -1 if error.
 */

int
m_send(M_SOCK so, char * data, unsigned datalen)
{
   PACKET   pkt;
   struct tcpcb * tp;
   unsigned sent, tosend;
   int      err;
   
   LOCK_NET_RESOURCE(NET_RESID);

   /* make sure connection is established. */
   tp = so->tp;
   if((tp == NULL) || (tp->t_state < TCPS_ESTABLISHED))
   {
      so->error = ESHUTDOWN;
      UNLOCK_NET_RESOURCE(NET_RESID);
      return -1;
   }

#ifdef NOTDEF
   /* see if we can copy the data to the end of the last queued send */
   if(so->sendq.sb_cc)
   {
      struct tcphdr * ptcp;

      pkt = (PACKET)so->sendq.q_tail;    /* get last packet in send queue */
      ptcp = (struct tcphdr *)(pkt->nb_prot - 20);

      /* make sure we have not already sent this pkt */
      if(ptcp->th_seq < tp->snd_nxt)
      {
         dtrap("tcpapi 1\n");    /* watch this first few times */
         if((pkt->nb_blen - (pkt->nb_prot + pkt->nb_plen - pkt->nb_buff)) >  datalen)
         {
            pkt->m_data += datalen;
            MEMCPY(pkt->m_data, data, datalen);
            so->sendq.sb_cc += datalen;
            pkt->m_len += datalen;
            tcp_output(so->tp);
            UNLOCK_NET_RESOURCE(NET_RESID);
            return datalen;
         }
      }
   }
#endif   /* NOTDEF */

   sent = 0;
   while(datalen > 0)
   {
      tosend = min(datalen, TCP_MSS);
      pkt = tcp_pktalloc(tosend);
      if(!pkt)
      {
         /* handle out-of-packets condition. */
         if((so->state & SS_NBIO) == 0)
         {
            /* blocking socket; wait for packets to become free */
            tcp_sleep(&so->sendq);  /* let system spin a bit */

            if((so->state & SS_ISCONNECTED) == 0)
            {
               /* socket closed while waiting, report this to caller. */
               so->error = ESHUTDOWN;
               goto rtnerr;
            }
            continue;      /* else loop back to wait some more */
         }

         /* fall to here if this is a non-blocking socket */
         if(sent == 0)     /* no bytes went out */
         {
            so->error = EWOULDBLOCK;
            goto rtnerr;
         }
         /* return number of bytes we sent before running out of buffers. */
         return sent;
      }
      MEMCPY(pkt->m_data, data, tosend);
      pkt->m_len = tosend;    /* set length in packet mbuf vars */

sendagain:
      UNLOCK_NET_RESOURCE(NET_RESID);
      err = tcp_send(so, pkt);   /* pass packet to tcp layer */
      LOCK_NET_RESOURCE(NET_RESID);

      /* See if socket is full to legal limit, */
      if(err == EWOULDBLOCK)
      {
         /* If socket is non-blocking, return now */
         if(so->state & SS_NBIO)
         {
            tcp_pktfree(pkt);    /* free last packet we allocated */
            if(sent == 0)        /* if no data went out, set error to explain why */
            {
               so->error = err;
               goto rtnerr;
            }
            goto rtn;           /* else return amount of data sent OK */
         }

         /* else sleep until some data is acked by remote host. */
         tcp_sleep(&so->sendq);
         goto sendagain;
      }
      else if(err)   /* error other than EWOULDBLOCK */
      {
         /* Return any other error code. Return -1 instead of "sent" so 
          * caller knows there was a hard error.
          */
         so->error = err;
         goto rtnerr;
      }
      /* packet sent OK, adjust data variables for next loop */
      data += tosend;         /* fix data pointer for amount copied */
      datalen -= tosend;      /* ...and data lengnth */
      sent += tosend;         /* ...and local byte counter */
   }

rtn:
   UNLOCK_NET_RESOURCE(NET_RESID);
   return sent;
rtnerr:
   UNLOCK_NET_RESOURCE(NET_RESID);
   return -1;
}

#endif   /* BSDISH_SEND */

#ifdef BSDISH_RECV

/* FUNCTION: m_recv()
 *
 * A workalike for the BSD sockets recv() call
 *
 * PARAM1: M_SOCK socket,
 * PARAM2: char * buffer
 * PARAM3: unsigned length
 *
 * RETURNS: number of bytes actually read, or -1 if error. 
 */

int
m_recv(M_SOCK so, char * buf, unsigned buflen)
{
   PACKET   pkt;
   int      tocopy;
   int      len;
   
   LOCK_NET_RESOURCE(NET_RESID);

   len = 0;    /* amount we have copied */

   /* handle the no data case first */
   while(so->rcvdq.sb_cc == 0)
   {
      /* If socket is disconnected (or disconnecting), indicate
       * this to the caller by returning a zero.
       */
      if((so->state & SS_CANTRCVMORE) 
#ifdef MINI_TCP_OOSQ
         && (so->oosq.p_head == NULL)
#endif
         )
      {
         so->error = ESHUTDOWN;
         goto rtn;
      }
      /* If THE socket is non-blocking and no data is ready, it 
       * returns -1 and error is set to EWOULDBLOCK.
       */
      if(so->state & SS_NBIO)
      {
         so->error = EWOULDBLOCK;
         len = -1;
         goto rtn;
      }
      UNLOCK_NET_RESOURCE(NET_RESID);
      tk_yield();
      LOCK_NET_RESOURCE(NET_RESID);
   }

   /* fall to here if socket has received data in queue */
   while((buflen > 0) && so->rcvdq.sb_cc)
   {
      /* move data from 1st pkt to caller's buffer */
      pkt = (PACKET)so->rcvdq.p_head;
      tocopy = min(buflen, pkt->m_len);
      MEMCPY(buf, pkt->m_data, tocopy);
      buflen -= tocopy;
      buf += tocopy;
      len += tocopy;

       /* dequeue data we moved */
      if(tocopy >= (int)pkt->m_len)
      {
         /* we moved whole packet, free it */
         tcp_pktfree(get_soq(&so->rcvdq));

         /* see if we need to update TCP rcv window */
         tcp_output(so->tp);
      }
      else  /* acked a partial packet */
      {
         /* drop data from head of packet */
         pkt->m_data += tocopy;
         pkt->m_len -= tocopy;
         so->rcvdq.sb_cc -= tocopy;
      }
   }
#ifdef NPDEBUG
   if(len == 0)
   {
      dtrap("tcpapi 2\n");    /* should never happen */
   }
#endif
rtn:
   UNLOCK_NET_RESOURCE(NET_RESID);
   return len;
}

#endif   /* BSDISH_RECV */

/* FUNCTION: tcpt_rangeset
 *
 * Force a time value to be in a certain range.
 *
 * PARAM1: short value,
 * PARAM2: short min.
 * PARAM3: short max.
 *
 * RETURNS: the time value, set within the range.
 */

short
tcpt_rangeset(short value, short tvmin, short tvmax)
{
   short tv = value; 

   if (value < tvmin)
      tv = (short)tvmin;
   else if (value > tvmax)
      tv = (short)tvmax;

   return tv;
}

#ifdef BSDISH_GETPEERNAME

/* m_getpeername() - NicheLite workalike to the BSD getpeername() */

int
m_getpeername(SOCKTYPE sock, struct sockaddr_in * addr)
{
   LOCK_NET_RESOURCE(NET_RESID);
   addr->sin_addr.s_addr = sock->fhost;
   addr->sin_port = sock->lport;
   UNLOCK_NET_RESOURCE(NET_RESID);

   return 0;   /* no real error checking */
}

#endif  /* BSDISH_GETPEERNAME */

⌨️ 快捷键说明

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