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

📄 transmit.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
   */
  if (*len > 0 && room <= socket->send_lowat)
     return (-1);

  /* streams may be split up, modify '*len'
   */
  *len = room;
  return (0);
}

/*
 *  TCP transmitter
 */
static int tcp_transmit (Socket *socket, const void *buf, int len, int flags)
{
  sock_type *sk = (sock_type*)socket->tcp_sock;

  tcp_tick (sk);
  tcp_Retransmitter (1);

  if (sk->tcp.state < tcp_StateESTAB || sk->tcp.state >= tcp_StateLASTACK)
  {
    socket->so_state |= SS_CANTSENDMORE;
    SOCK_DEBUGF ((socket, ", ENOTCONN (%s)",  /* !! or EPIPE */
                 (sk->tcp.locflags & LF_GOT_FIN) ?
                   "got FIN" : "can't send"));
    SOCK_ERR (ENOTCONN);
    return (-1);
  }

  if (socket->so_state & SS_NBIO)
  {
    int in_len = len;

    if (check_non_block_tx(socket,&len) < 0)
    {
      SOCK_DEBUGF ((socket, ", EWOULDBLOCK"));
      SOCK_ERR (EWOULDBLOCK);
      return (-1);
    }
    if (in_len != len)
       SOCK_DEBUGF ((socket, " [%d]", len)); /* trace "len=x [y]" */
  }

  SOCK_DEBUGF ((socket, ", %s (%d) / TCP",
                inet_ntoa(socket->remote_addr->sin_addr),
                ntohs(socket->remote_addr->sin_port)));

#if 0
  /* Must wait for room in send buffer
   */
  if ((flags & MSG_WAITALL) || len > sock_tbleft(sk))
       len = sock_write (sk, (BYTE*)buf, len);
  else len = sock_fastwrite (sk, (BYTE*)buf, len);

#else
  /* This is more efficient. The above sock_fastwrite() would
   * effectively turn off Nagle's algorithm.
   */
  ARGSUSED (flags);
  len = sock_write (sk, (BYTE*)buf, len);
#endif

  if (len <= 0)    /* error in tcp_write() */
  {
    if (sk->tcp.state != tcp_StateESTAB)
    {
      SOCK_DEBUGF ((socket, ", ENOTCONN"));
      SOCK_ERR (ENOTCONN);   /* maybe EPIPE? */
    }
    else
    {
      SOCK_DEBUGF ((socket, ", ENETDOWN"));
      SOCK_ERR (ENETDOWN);
    }
    return (-1);
  }
  return (len);
}


/*
 *  UDP transmitter
 */
static int udp_transmit (Socket *socket, const void *buf, int len)
{
  sock_type *sk   = (sock_type*) socket->udp_sock;
  u_long     dest = socket->remote_addr->sin_addr.s_addr;
  int        tx_room, rc;
  int        is_bcast, is_multi;

  if (!tcp_tick(sk))
  {
    socket->so_state |= SS_CANTSENDMORE;
    SOCK_DEBUGF ((socket, ", ENOTCONN (can't send)")); /* !! or EPIPE */
    SOCK_ERR (ENOTCONN);
    return (-1);
  }
  tcp_Retransmitter (1);

  if ((socket->so_state & SS_NBIO) && check_non_block_tx(socket,&len) < 0)
  {
    SOCK_DEBUGF ((socket, ", EWOULDBLOCK"));
    SOCK_ERR (EWOULDBLOCK);
    return (-1);
  }

  is_bcast = (dest == INADDR_BROADCAST || dest == INADDR_ANY);
  is_multi = IN_MULTICAST (ntohl(socket->remote_addr->sin_addr.s_addr));

  SOCK_DEBUGF ((socket, ", %s (%d) / UDP %s",
                inet_ntoa(socket->remote_addr->sin_addr),
                ntohs(socket->remote_addr->sin_port),
                is_multi ? "(mc)" : ""));

  if (len == 0)   /* 0-byte probe packet */
     return ip_transmit (socket, NULL, 0);

  tx_room = sock_tbleft (sk);  /* always MTU-28 */

  /* Special tests for broadcast messages
   */
  if (is_bcast)
  {
    if (len > tx_room)        /* don't allow fragments */
    {
      SOCK_DEBUGF ((socket, ", EMSGSIZE"));
      SOCK_ERR (EMSGSIZE);
      STAT (ipstats.ips_odropped++);
      return (-1);
    }
    if (_pktserial)           /* Link-layer doesn't allow broadcast */
    {
      SOCK_DEBUGF ((socket, ", EADDRNOTAVAIL"));
      SOCK_ERR (EADDRNOTAVAIL);
      STAT (ipstats.ips_odropped++);
      return (-1);
    }
  }

  /* set new TTL if setsockopt() used before sending to Class-D socket
   */
  if (is_multi)
     sk->udp.ttl = socket->ip_ttl;

#if defined(USE_FRAGMENTS)
  if ((long)len > USHRT_MAX - sizeof(udp_Header))
  {
    SOCK_DEBUGF ((socket, ", EMSGSIZE"));
    SOCK_ERR (EMSGSIZE);
    STAT (ipstats.ips_toolong++);
    return (-1);
  }

  if (len > tx_room)
     return SEND_IP_FRAGMENTS (sk, UDP_PROTO, dest, buf, len);
#endif

  rc = sock_write (sk, (BYTE*)buf, len);
  if (rc <= 0)    /* error in udp_write() */
  {
    SOCK_DEBUGF ((socket, ", ENETDOWN"));
    SOCK_ERR (ENETDOWN);
    return (-1);
  }
  return (rc);
}

/*
 *  Raw IP transmitter
 */
static int ip_transmit (Socket *socket, const void *tx, int len)
{
  eth_address eth;
  u_long      dest;
  unsigned    tx_len, tx_room;
  sock_type  *sk = (sock_type*)socket->udp_sock;

  struct ip   *ip  = (struct ip*) tx;
  const  BYTE *buf = (const BYTE*) tx;
  WORD   flags     = 0;
  DWORD  offset;
  UINT   h_len, o_len;

  tcp_tick (NULL);        /* process other TCBs too */
  tcp_Retransmitter (1);

  /* This should never happen
   */
  if (ip && (socket->so_state & SS_NBIO) &&
      sock_tbleft(sk) < (len + socket->send_lowat))
  {
    SOCK_DEBUGF ((socket, ", EWOULDBLOCK"));
    SOCK_ERR (EWOULDBLOCK);
    return (-1);
  }

  if (ip)
  {
    offset = ntohs (ip->ip_off);
    flags  = offset & ~IP_OFFMASK;
    offset = (offset & IP_OFFMASK) << 3; /* 0 <= ip_ofs <= 65536-8 */
  }

  SOCK_DEBUGF ((socket, ", %s / Raw",
                inet_ntoa(socket->remote_addr->sin_addr)));

  if (ip && (socket->inp_flags & INP_HDRINCL))
  {
    dest    = ip->ip_dst.s_addr;
    tx_len  = len;
    tx_room = mtu;
  }
  else
  {
    dest    = socket->remote_addr->sin_addr.s_addr;
    tx_len  = len + sizeof (*ip);
    tx_room = mtu + sizeof (*ip);
  }

  if (!dest || !_arp_resolve(ntohl(dest),&eth,0))
  {
    SOCK_DEBUGF ((socket, ", no route"));
    SOCK_ERR (EHOSTUNREACH);
    STAT (ipstats.ips_noroute++);
    return (-1);
  }

#if defined(USE_FRAGMENTS)
  if (!(socket->inp_flags & INP_HDRINCL) &&
      tx_len + socket->ip_opt_len > tx_room)
  {
    sk = (sock_type*)socket->raw_sock;

    if (flags & IP_DF)
    {
      SOCK_DEBUGF ((socket, ", EMSGSIZE"));
      SOCK_ERR (EMSGSIZE);
      STAT (ipstats.ips_toolong++);
      return (-1);
    }
    return SEND_IP_FRAGMENTS (sk, sk->raw.ip_type, dest, buf, len);
  }
#else
  if (!(socket->inp_flags & INP_HDRINCL) &&
      tx_len + socket->ip_opt_len > tx_room)
  {
    SOCK_DEBUGF ((socket, ", EMSGSIZE"));
    SOCK_ERR (EMSGSIZE);
    STAT (ipstats.ips_toolong++);
    return (-1);
  }
#endif

  ip = (struct ip*) _eth_formatpacket (&eth, IP_TYPE);

  if (socket->inp_flags & INP_HDRINCL)
  {
    memcpy (ip, buf, len);
    if (ip->ip_src.s_addr == 0)
    {
      ip->ip_src.s_addr = gethostid();
      ip->ip_sum = 0;
      ip->ip_sum = ~checksum ((void*)ip, ip->ip_hl << 2);
    }
    if (ip->ip_sum == 0)
        ip->ip_sum = ~checksum ((void*)ip, ip->ip_hl << 2);
  }
  else
  {
    if (socket->ip_opt && socket->ip_opt_len > 0)
    {
      BYTE *data;

      o_len = min (socket->ip_opt_len, sizeof(socket->ip_opt->ip_opts));
      h_len = sizeof(*ip) + o_len;
      data  = (BYTE*)ip + h_len;
      memcpy (ip+1, &socket->ip_opt->ip_opts, o_len);
      memcpy (data, buf, len);
      tx_len += o_len;
      if (socket->ip_opt->ip_dst.s_addr)   /* using source routing */
         dest = socket->ip_opt->ip_dst.s_addr;
    }
    else
    {
      if (buf)
         memcpy (ip+1, buf, len);
      h_len = sizeof (*ip);
    }

    ip->ip_v   = IPVERSION;
    ip->ip_hl  = h_len >> 2;
    ip->ip_tos = socket->ip_tos;
    ip->ip_len = htons (tx_len);
    ip->ip_id  = _get_ip_id();
    ip->ip_off = 0;
    ip->ip_ttl = socket->ip_ttl;
    ip->ip_p   = socket->so_proto;

    ip->ip_src.s_addr = gethostid();
    ip->ip_dst.s_addr = dest;

    ip->ip_sum = 0;
    ip->ip_sum = ~checksum (ip, h_len);
  }

  DEBUG_TX (NULL, ip);

  if (!_eth_send(tx_len))
  {
    SOCK_DEBUGF ((socket, ", ENETDOWN"));
    SOCK_ERR (ENETDOWN);
    return (-1);
  }
  if (buf)
     buf += tx_len;

  return (len);
}
#endif  /* USE_BSD_FUNC */

⌨️ 快捷键说明

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