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

📄 tcputil.c

📁 在ARM7和UC/OSII的平台上实现了GPS自动报站的功能,涉及GPS模块LEA_4S的驱动,位置速寻算法,语音芯片ISD4004的录放音驱动,LED页面管理等等.从启动代码到操作系统的移植以及到业
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * FILENAME: tcputil.c
 *
 * Copyright 2000-2002 InterNiche Technologies Inc. All rights reserved.
 *
 *
 * MODULE: MTCP
 *
 * ROUTINES: msoq_check(), m_setlport(), m_tcpdrop(),
 * ROUTINES: m_tcpclose(), m_data_upcall(), m_newtcpcb(), so_flush(),
 * ROUTINES: so_lookup(), m_delsocket(), m_template(), m_connected(),
 * ROUTINES: m_disconnecting(), m_sbdrop(), get_soq(), put_soq(),
 * ROUTINES: socket_queue_name()
 *
 *
 * PORTABLE: yes
 */


#include "ipport.h"
#include "mtcp.h"
#define Debug_tcputil	0xff
#if Debug_tcputil <= 0x03
#include "uartdrv.h"
#endif
//#include "ZPrint.h"
void tcp_wakeup(void * event);	/* (yaxon add) */

struct queue msoq;         /* global queue of M_SOCK structs */

static unshort nextlport;  /* next lport to assign in m_setlport() */

/* NEXTLPORT_LL - lower limit for nextlport */
#ifndef NEXTLPORT_LL
#define NEXTLPORT_LL       1024
#endif

/* NEXTLPORT_UL - upper limit for nextlport */
#ifndef NEXTLPORT_UL
#define NEXTLPORT_UL       65534
#endif

#ifdef NET_STATS
struct tcpstat tcpstat;    /* BSD tcp statistics */
#endif

int   TCPTV_MSL = (4 * PR_SLOWHZ);     /* max seg lifetime default */

#ifdef INCLUDE_SNMP
struct tcp_mib tcpmib;
#else    /* no SNMP, support tcp_mib locally for tcp_stats() */
struct TcpMib tcpmib;
#endif


#ifdef MSOQ_CHECK
/* sanity check of soq */
void
msoq_check()
{
   int ct;
   M_SOCK so;
   ct = 1;

   if(msoq.q_head == NULL)
   {
      if(msoq.q_tail != NULL)
      {
         dtrap("tcputil 0\n");
      }
      if(msoq.q_len != 0)
      {
         dtrap("tcputil 1\n");
      }
   }
   for(so =  (M_SOCK)(msoq.q_head); so->next; so = so->next)
   {
      ct++;
   }
   if(so != (M_SOCK)(msoq.q_tail))
   {
      dtrap("tcputil 2\n");
   }
   if(ct != msoq.q_len)
   {
      dtrap("tcputil 3\n");
   }

}
#endif   /* MSOQ_CHECK */

/* FUNCTION: m_setlport()
 *
 * Sets the socket's lport (local port number) to a reasonable
 * non-zero value.
 *
 * PARAM1: M_SOCK so; the socket whose lport is to be set
 *
 * RETURNS: void;
 */
void
m_setlport(M_SOCK so)
{
   M_SOCK qso;

restart:
   /* guess the nextlport based on the last one +1, but constrain
    * it to be in the range [NEXTLPORT_LL...NEXTLPORT_UL] (inclusive)
    */
   if ((nextlport >= NEXTLPORT_LL) && (nextlport < NEXTLPORT_UL))
      nextlport++;
   else
      nextlport = NEXTLPORT_LL;
   nextlport = htons(nextlport);

   /* verify that nextlport is available by walking the socket
    * list and verifying that it's not in use
    */
   ENTER_CRIT_SECTION(&msoq);
   for (qso = (M_SOCK)(msoq.q_head); qso->next; qso = qso->next)
   {
      /* if it's not available, start over with new nextlport */
      if (qso->lport == nextlport)
      {
         EXIT_CRIT_SECTION(&msoq);
         goto restart;
      }
   }
   EXIT_CRIT_SECTION(&msoq);

   /* use nextlport to set the socket's lport */
   so->lport = nextlport;
   nextlport = ntohs(nextlport);

}

/* FUNCTION: m_tcpdrop()
 *
 * Drop a TCP connection, reporting
 * the specified error.  If connection is synchronized,
 * then send a RST to peer.
 *
 * In BSD this is tcp_drop().
 *
 * PARAM1: struct tcpcb *tp
 * PARAM2: int err
 *
 * RETURNS:
 */

void
m_tcpdrop(struct tcpcb * tp, int err)
{
   M_SOCK so =  (M_SOCK)tp->t_inpcb;

   /* set socket error for upcall to app */
   so->error = err;

   /* if socket was past LISTEN state, notify app that it's going away */
   if((so->callback) && (tp->t_state > TCPS_LISTEN)){
#if Debug_tcputil <= 0x03
      PrintFromUART(Debug_tcpin,"tcputil Close!\n");
#endif
      so->callback(M_CLOSED, so, NULL);
   }
   /* If connected, send reset to peer */
   if (TCPS_HAVERCVDSYN(tp->t_state))
   {
      tp->t_state = TCPS_CLOSED;
      (void) tcp_output(tp);
      TCP_STAT_INC(tcps_drops);
   }
   else
      TCP_STAT_INC(tcps_conndrops);

   m_tcpclose(tp);
}


/* FUNCTION: m_tcpclose()
 *
 * Close a TCP control block:
 *   discard all space held by the tcp
 *   discard internet protocol block
 *   wake up any sleepers
 *
 * In BSD this is tcp_close().
 *
 * PARAM1: struct tcpcb *tp
 *
 * RETURNS:
 */

void
m_tcpclose(struct tcpcb * tp)
{
   M_SOCK so =  (M_SOCK)tp->t_inpcb;

   so_flush(so);
   TCB_FREE (tp);
   so->tp = NULL;       /* prevent further refs to tp */
   m_disconnected(so);
   TCP_STAT_INC(tcps_closed);
}


/* FUNCTION: m_data_upcall()
 *
 * called by tcp_input() when data is received
 * for a socket with an upcall handler set. The upcall handler is a
 * m_socket structure member.
 *
 * The upcall routine description is as follows:
 *
 * int rx_upcall(struct socket so, PACKET pkt, int error);
 *
 * ....where: so is socket which got data. pkt - pkt containing recieved
 * data, or NULL if error. error is 0 if good pkt, else BSD socket
 * error
 *
 *    The upcall() returns 0 if it accepted data, non-zero if not.
 * End of file is signaled to the upcall by ESHUTDOWN eror code. If
 * LOCK_NET_RESOURCE() is used, the resource is already locked when
 * the upcall is called. The upcall will NOT be called from inside a
 * CRIT_SECTION macro pairing.
 *
 *
 * PARAM1: m_socket
 *
 * RETURNS: nothing
 */

void
m_data_upcall(M_SOCK so)
{
   int      err;
   PACKET   pkt;

   /* don't upcall application if there's no data */
   if (so->rcvdq.sb_cc == 0)
      return;

   /* don't re-enter the upcall routine */
   if (so->state & SS_INUPCALL)
      return;

   /* Set flags. SS_UPCALLED is used by select() logic to wake sockets blocked
    * on receive, SS_INUPCALL is the re-entry guard.
    */
   so->state |= (SS_UPCALLED|SS_INUPCALL);

   while(so->rcvdq.p_head)
   {
      pkt = so->rcvdq.p_head;
      err = so->callback(M_RXDATA, so, pkt);
      if(err)     /* if app returned error, quit */
         break;

      /* dequeue the packet data the application just accepted */
      get_soq(&so->rcvdq);
      tcp_pktfree(pkt);
   }
   so->state &= ~SS_INUPCALL;    /* clear re-entry flag */
   return;
}


/* FUNCTION: tcp_newtcpcb()
 *
 * Create a new TCP control block, making an
 * empty reassembly queue and hooking it to the argument
 * protocol control block.
 *
 * PARAM1: struct inpcb *inp
 *
 * RETURNS:
 */

struct tcpcb *
m_newtcpcb(M_SOCK so)
{
   struct tcpcb * tp;
   short t_time;

   tp = TCB_ALLOC(sizeof (*tp));
   if (tp == NULL)
      return (struct tcpcb *)NULL;
   tp->t_maxseg = TCP_MSS;
   tp->t_flags = 0;        /* sends options! */

   /* install back pointer to socket */
   tp->t_inpcb = (struct inpcb *)so;
   so->tp = tp;

   /*
    * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
    * rtt estimate.  Set rttvar so that srtt + 2 * rttvar gives
    * reasonable initial retransmit time.
    */
   tp->t_srtt = TCPTV_SRTTBASE;
   tp->t_rttvar = TCPTV_SRTTDFLT << 2;

   t_time = ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1;
   TCPT_RANGESET(tp->t_rxtcur, t_time, TCPTV_MIN, TCPTV_REXMTMAX);
   tp->snd_cwnd = (u_short)(mt_deftxwin);
   tp->snd_ssthresh = 65535;        /* XXX */
   return (tp);
}


/* FUNCTION: so_flush()
 *
 * Free all the buffers in a socket's receive and send
 * queues in preparation for termination.
 *
 * PARAM1: socket
 *
 * RETURNS: none
 */


void
so_flush(M_SOCK so)
{
   while(so->sendq.p_head)
      tcp_pktfree(get_soq(&so->sendq));
   while(so->rcvdq.p_head)
      tcp_pktfree(get_soq(&so->rcvdq));
   while(so->oosq.p_head)
      tcp_pktfree(get_soq(&so->oosq)); 	    //free oosq modify by zealea
   so->state |= (SS_CANTRCVMORE|SS_CANTRCVMORE);
}


/* FUNCTION: so_lookup()
 *
 *    Look up the first socket matching the passed received
 * IP and TCP headers.
 *    This allows the socket to contain wildcard(0) foreign tupple members,
 * but tries for an exact match first.
 *
 * PARAM1: IP header with IP addresses to match
 * PARAM2: TCP header with ports to match
 *
 * RETURNS: matching socket if found, else null.
 */

M_SOCK
so_lookup(struct ip * pip, struct tcphdr * ptcp)
{
   M_SOCK so;        /* scratch */
   M_SOCK wild;      /* socket which had a wildcard match */

msoq_check();
   wild = NULL;
   for(so = (M_SOCK)msoq.q_head; so; so = so->next)
   {
      /* local port must always match - do quick test */
      if(so->lport != ptcp->th_dport)
         continue;   /* not even a partial match */

⌨️ 快捷键说明

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