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

📄 pctcp.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
        {
          s->hisport = srcPort;  /* remember his IP-address */
          s->hisaddr = source;   /*   and src-port */
          s->myaddr  = destin;   /* socket is now active */
          break;
        }
  }

  DEBUG_RX (s, ip);

  if (!s)
  {
    if (!(flags & tcp_FlagRST))              /* don't answer RST */
       TCP_RESET (NULL, ip, tcp);

    else if ((flags & tcp_FlagACK) &&           /* got ACK,RST   */
             (s = tcp_findseq(ip,tcp)) != NULL) /* ACK = SEQ + 1 */
            tcp_sockreset (s, 1);  /* e.g. a firewall is sending */
    STAT (tcpstats.tcps_drops++);  /* RST for server on inside   */
    return (NULL);
  }

  /* Restart idle-timer
   */
  if (sock_inactive && !(s->locflags & LF_RCVTIMEO))
     s->inactive_to = set_timeout (1000 * sock_inactive);

  if (flags & tcp_FlagRST)         /* got reset code */
  {
    tcp_sockreset (s, 0);
    return (NULL);
  }

  tcp_rtt_wind (s);       /* update retrans timer, windows etc. */

  if (_tcp_fsm(&s,ip) &&  /* do input tcp state-machine */
      s->unhappy)         /* if "unhappy", retransmit soon */
     TCP_SENDSOON (s);

  return (s);
}
#endif  /* !USE_UDP_ONLY */


/*
 * Handler for incoming udp packets.
 */
static udp_Socket *udp_handler (const in_Header *ip, BOOL broadcast)
{
  udp_Socket      *s;
  udp_Header      *udp;
  tcp_PseudoHeader ph;

  WORD  len, dstPort, srcPort;
  DWORD destin   = intel (ip->destination);
  BOOL  ip_bcast = broadcast ||        /* link-layer broadcast */
                   is_ip_brdcast(ip);  /* (directed) ip-broadcast */

#if !defined(USE_MULTICAST)

  /* dst = ip number
   *     or 255.255.255.255
   *     or sin_mask.255.255
   * This is the only really gross hack in the multicasting stuff.
   * I'll fix it as soon as I can figure out what I want to do here.
   * -JRM 8/1/93
   */
  if (!ip_bcast &&                        /* not a broadcast packet */
      destin - my_ip_addr > multihomes && /* not my address         */
      my_ip_addr)                         /* and I know my address  */
  {
    DEBUG_RX (NULL, ip);
    return (NULL);
  }
#endif

  len = in_GetHdrLen (ip);
  udp = (udp_Header*) ((BYTE*)ip + len);   /* udp segment pointer */
  len = intel16 (udp->length);

  if (len < sizeof(*udp))
  {
    DEBUG_RX (NULL, ip);
    STAT (udpstats.udps_hdrops++);
    return (NULL);
  }

  srcPort = intel16 (udp->srcPort);
  dstPort = intel16 (udp->dstPort);

  /* demux to active sockets
   */
  for (s = _udp_allsocs; s; s = s->next)
  {
    if (s->safetysig != SAFETYUDP)
    {
      outsnl (_LANG("udp-socket error in udp_handler()"));
      DEBUG_RX (s, ip);
      return (NULL);
    }
    if (!ip_bcast               &&
        (s->hisport != 0)       &&
        (dstPort == s->myport)  &&
        (srcPort == s->hisport) &&
        ((destin & sin_mask) == (s->myaddr & sin_mask)) &&
        (intel(ip->source)   == s->hisaddr))
       break;
  }

  if (!s)
  {
    /* demux to passive sockets
     */
    for (s = _udp_allsocs; s; s = s->next)
    {
      if ((s->hisaddr == 0 || s->hisaddr == 0xFFFFFFFFUL) &&
          dstPort == s->myport)
      {
        if (s->hisaddr == 0)
        {
          s->hisaddr = intel (ip->source);
          s->hisport = srcPort;
          SET_PEER_MAC_ADDR (s, ip);

          /* take on value of expected destination
           * unless it is broadcast
           */
          if (!ip_bcast)
             s->myaddr = destin;
        }
        break;
      }
    }
  }

  DEBUG_RX (s, ip);

#if defined(USE_MULTICAST)
  if (!s)
  {
    /* demux to multicast sockets
     */
    for (s = _udp_allsocs; s; s = s->next)
    {
      if (s->hisport != 0         &&
          s->hisaddr == destin    &&
          dstPort    == s->myport &&
          is_multicast(destin))
        break;
    }
  }
#endif

  if (!s)
  {
    /* Demux to broadcast sockets.
     */
    for (s = _udp_allsocs; s; s = s->next)
    {
      if (s->hisaddr == (DWORD)-1 && dstPort == s->myport)
         break;
    }
  }

  if (!s)  /* no demultiplexer found anything */
  {
    if (debug_on)
       outs (_LANG("discarding..."));

    if ((destin - my_ip_addr <= multihomes) && my_ip_addr)
    {
      if (!ip_bcast &&              /* broadcast? */
          srcPort != DOM_DST_PORT)  /* from a nameserver?  */
         icmp_unreach (ip, 3);      /* send port unreachable */

      if (ip_bcast)
           STAT (udpstats.udps_noportbcast++);
      else STAT (udpstats.udps_noport++);
    }
    return (NULL);
  }

  /* these parameters are used for things other than just checksums
   */
  memset (&ph, 0, sizeof(ph));
  ph.src      = ip->source;      /* already network order */
  ph.dst      = ip->destination;
  ph.protocol = UDP_PROTO;
  ph.length   = udp->length;
  ph.checksum = checksum (udp, len);

  if (udp->checksum && (s->sockmode & UDP_MODE_NOCHK) == 0)
  {
    if (checksum(&ph,sizeof(ph)) != 0xFFFF)
    {
      if (debug_on)
         outsnl (_LANG("bad udp checksum"));
      STAT (udpstats.udps_badsum++);
      return (s);
    }
  }

  /* Process user data. 0-byte probe is legal for s->protoHandler.
   */
  {
    BYTE *data = (BYTE*)(udp+1);

    len -= sizeof(*udp);
    if (s->protoHandler)
      (*s->protoHandler) (s, data, len, &ph, udp);
    /* save first received packet rather than latest */
    else if (len > 0 && s->rdatalen == 0)
    {
      if (len > s->maxrdatalen)   /* truncate data :-( */
      {
        len = s->maxrdatalen;
        STAT (udpstats.udps_fullsock++);
      }
      /* Might overwrite previous data! But hey, this is UDP..
       */
      memcpy (s->rdata, data, len);
      s->rdatalen = len;
    }
  }
  return (s);
}


/*
 * tcp_Retransmit() - called periodically to perform retransmissions.
 *                  - if 'force == 1' do it now.
 */
void tcp_Retransmitter (int force)
{
#if defined(USE_UDP_ONLY)
  ARGSUSED (force);
#else
  tcp_Socket *s, *next;

  static DWORD timeout = 0UL;

  /* do this once per tcp_RETRAN_TIME
   */
  if (!force && timeout && !chk_timeout(timeout))
     return;

  timeout = set_timeout (tcp_RETRAN_TIME);

  for (s = _tcp_allsocs; s; s = next)
  {
    next = s->next;

    /* possible to be closed but still queued
     */
    if (s->state == tcp_StateCLOSED)
    {
      if (s->rdatalen == 0)
      {
        maybe_reuse_lport (s);
        next = _tcp_unthread (s);
      }
      continue;
    }

    if (s->datalen > 0 || s->unhappy || s->karn_count == 1)
    {
      if (chk_timeout(s->rtt_time))  /* retransmission timeout */
      {
        s->rtt_time = 0UL;           /* stop RTT timer */

#if defined(USE_DEBUG)
        if (debug_on > 1)
          (*_printf) ("regular retran TO set unacked back to 0 from %u\r\n",
                      s->unacked);
#endif
        /* strategy handles closed windows.  JD + EE
         */
        if (s->window == 0 && s->karn_count == 2)
            s->window = 1;

        if (s->karn_count == 0)
        {
          /* Simple "Slow start" algorithm:
           * Use the backed off RTO - implied, no code necessary.
           * Reduce the congestion window by 25%
           */
          unsigned cwindow = ((unsigned)(s->cwindow + 1) * 3) >> 2;

          s->cwindow = cwindow;
          if (s->cwindow == 0)
              s->cwindow = 1;

          s->wwindow = 0;       /* dup ACK counter ? */
       /* s->snd_ssthresh = s->cwindow * s->max_seg; */ /* !!to-do */

          /* if really did timeout
           */
          s->karn_count = 2;
          s->unacked    = 0;
        }
        if (s->datalen > 0)
            s->flags |= (tcp_FlagPUSH | tcp_FlagACK);

        if (s->unhappy)
           STAT (tcpstats.tcps_rexmttimeo++);

        else if (s->flags & tcp_FlagACK)
           STAT (tcpstats.tcps_delack++);

        (void) TCP_SEND (s);
      }

      /* handle inactive tcp timeouts (not sending data)
       */
      if (chk_timeout(s->datatimer))  /* EE 99.08.23 */
      {
        s->err_msg = _LANG("Connection timed out - no data sent");
        tcp_abort (s);
      }
    }  /* end of retransmission strategy */


    /* handle inactive tcp timeouts (not received anything)
     */
    if (chk_timeout(s->inactive_to))
    {
      /* this baby has timed out. Don't do this again.
       */
      s->inactive_to = 0UL;
      s->err_msg = _LANG("Connection timed out - no activity");
      sock_close ((sock_type*)s);
    }
    else if (chk_timeout(s->timeout))
    {
      if (s->state == tcp_StateTIMEWT)
      {
        s->state = tcp_StateCLOSED;
        break;
      }
      else if (s->state != tcp_StateESTAB && s->state != tcp_StateESTCL)
      {
        s->err_msg = _LANG("Timeout, aborting");
        tcp_abort (s);
        break;
      }
    }
  }
#endif /* !USE_UDP_ONLY */
}


/*
 *  ip_handler - do a simple check on IP header
 *             - Demultiplex packet to correct protocol handler
 */
int _ip_handler (in_Header *ip, BOOL broadcast)
{
  sock_type *s = NULL;

  if (block_ip || !_chk_ip_header(ip))
     return (0);

#if 0
  /* to-do: check for LSRR option and replace ip->source
   */       with actual source-address burried in option
   *        (ref. RFC1122)
#endif

#if defined(USE_BSD_FUNC)
  /*
   * Match 'ip' against all SOCK_RAW sockets before doing normal
   * protocol multiplexing below.
   *
   * Note: _raw_ip_hook is only set if we have allocated at least
   *       one SOCK_RAW socket. Don't waste time searching otherwise.
   *
   * Fix-me: a raw socket may gobble up a packet we're awaiting in
   *         e.g. resolve().
   */
  if (_raw_ip_hook && (*_raw_ip_hook)(ip))
     return (1);
#endif

  switch (ip->proto)
  {
#if !defined(USE_UDP_ONLY)
    case TCP_PROTO:
         s = (sock_type*) tcp_handler (ip, broadcast);
         break;
#endif

    case UDP_PROTO:
         s = (sock_type*) udp_handler (ip, broadcast);
         break;

    case ICMP_PROTO:
         icmp_handler (ip, broadcast);
         break;

#if defined(USE_MULTICAST)
    case IGMP_PROTO:
         igmp_handler (ip, broadcast);
         break;
#endif
    default:
         if (!broadcast)
         {
           if (is_local_addr (intel(ip->destination)))
              icmp_unreach (ip, 2);  /* protocol unreachable */
           DEBUG_RX (NULL, ip);
           STAT (ipstats.ips_noproto++);
         }
         return (0);
  }

  if (s)    /* Check if peer allows IP-fragments */
  {
    if (intel16(ip->frag_ofs) & IP_DF)
         s->tcp.locflags |=  LF_NOFRAGMENT;
    else s->tcp.locflags &= ~LF_NOFRAGMENT;
  }

  STAT (ipstats.ips_delivered++);
  return (1);
}


/*
 * tcp_tick - called periodically by user application
 *          - called with socket parameter or NULL
 *          - returns 1 when our socket closes
 */
WORD tcp_tick (sock_type *s)
{
  static DWORD daemon_timer = 0UL;

#if !defined(USE_UDP_ONLY)
  /* finish off dead sockets
   */
  if (s)
  {
    if ((s->tcp.ip_type  == TCP_PROTO)       &&
        (s->tcp.state    == tcp_StateCLOSED) &&
        (s->tcp.rdatalen == 0))
    {
      (void) _tcp_unthread (&s->tcp);
      s->tcp.ip_type = 0;   /* fail further I/O */
    }
  }
#endif

  while (1)
  {
    WORD eth_type = 0;
    BOOL brdcast  = FALSE;
    void *packet  = _eth_arrived (&eth_type, &brdcast);

    if (!packet)  /* packet points to network layer protocol */
       break;

    switch (eth_type)
    {
      case IP_TYPE:
           _ip_handler ((in_Header*)packet, brdcast);
           break;

      case ARP_TYPE:
           _arp_handler ((arp_Header*)packet);
           break;

#if defined(USE_PPPOE)
      case PPPOE_DISC_TYPE:
      case PPPOE_SESS_TYPE:
           pppoe_handler ((struct pppoe_Packet*)packet);
           break;
#endif
      /* RARP is only used during boot. Not needed here */
    }
    _eth_free (packet, eth_type);
  }

#if defined(USE_MULTICAST)
  if (_multicast_on)
     check_mcast_reports();
#endif

#if !defined(USE_UDP_ONLY)
  tcp_Retransmitter (0); /* check for our outstanding packets */
#endif

  if ((daemon_timer == 0UL || chk_timeout(daemon_timer)) && wattcpd)
  {
    (*wattcpd)();        /* do our various daemons */
    daemon_timer = set_timeout (DAEMON_RUN_TIME);
  }

  return (s ? s->tcp.ip_type : 0);
}

/*
 * udp_write()
 */
static int udp_write (udp_Socket *s, const BYTE *data, int len)
{
  #include <sys/packon.h>
  struct udp_pkt {
         in_Header  in;
         udp_Header udp;
      /* BYTE       data[]; */
       } *pkt;
  #include <sys/packoff.h>

  tcp_PseudoHeader ph;
  in_Header       *ip;
  udp_Header      *udp;
  mac_address     *dst;

  /* build link-layer header
   */
  dst = (_pktserial ? NULL : &s->hisethaddr);
  pkt = (struct udp_pkt*) _eth_formatpacket (dst, IP_TYPE);
  ip  = &pkt->in;
  udp = &pkt->udp;

  /* build udp header
   */
  udp->srcPort  = intel16 (s->myport);
  udp->dstPort  = intel16 (s->hisport);
  udp->checksum = 0;
  udp->length   = intel16 (sizeof(*udp)+len);

  memcpy (pkt+1, data, len);   /* copy 'data' to 'pkt->data[]' */
  memset (&ph, 0, sizeof(ph));
  ph.src = intel (s->myaddr);
  ph.dst = intel (s->hisaddr);

  if (!(s->sockmode & UDP_MODE_NOCHK))
  {
    ph.protocol = UDP_PROTO;
    ph.length   = udp->length;
    ph.checksum = checksum (udp, sizeof(*udp)+len);
    udp->checksum = ~checksum (&ph, sizeof(ph));
  }
  if (!IP_OUTPUT(ip, ph.src, ph.dst, UDP_PROTO, s->ttl,
                 (BYTE)_default_tos, 0, sizeof(*udp)+len, s))
     return (-1);
  return (len);
}

/*
 * udp_read - read socket data to 'buf', does large buffering
 */
static int udp_read (udp_Socket *s, BYTE *buf, int maxlen)
{
  int len = s->rdatalen;

  if (maxlen < 0)
      maxlen = INT_MAX;

  if (len > 0)
  {
    if (len > maxlen)
        len = maxlen;

⌨️ 快捷键说明

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