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

📄 pctcp.c

📁 dos下开发TCP网络的库文件部分
💻 C
📖 第 1 页 / 共 5 页
字号:
                                icmp_handler(ip);
                                break;
                        }
                    } else  {
#ifdef DEBUG
                        if (debug_on) outs("\n\rIP: Bad Checksum\n\r"); // R. Whitby
#endif
                    }
                    break;
                case /*0x806*/ 0x608 :
                    /* do arp */
                    _arp_handler( (arp_Header *)ip );
                    break;
                }
                if (ip) _eth_free(ip);

                continue;
    }
    /* check for our outstanding packets */
        tcp_Retransmitter();

// S. Lawson     return( s->udp.ip_type );
    return( s ? s->udp.ip_type : 1 );        /* S. Lawson - change CJ01 */
}

void tcp_set_debug_state( int x )
{
    debug_on = x;
}

/* returns 1 if connection is established */
int tcp_established( tcp_Socket *s )
{
    return( s->state >= tcp_StateESTAB );
}

/*
 * udp_write() handles fragmented UDP by assuming it'll be called
 *     once for all fragments with no intervening calls.  This is
 *     the case in sock_write().
 * Handles upto a hair-under 32K datagrams.  Could be made to handle
 *     upto a hair-under 64K easily...  wanna Erick?
 * Might be possible to test 'offset' for non/zero fewer times to be
 *     more efficient.  Might also be more efficient to use the old
 *     UDP checksum() call when more_frags is false in the first frag
 *     (i.e., not a fragmented dgram).
 * Uses _mss to decide splits which defaults to 1400.  Could pack
 *     more into an Ethernet packet.
 */
#define IP_MF 0x0020               // more fragments, net byte order

static udp_write( udp_Socket *s, byte *datap, int len, word offset )
{
    struct {                    // special pseudo header because need to
        tcp_PseudoHeader ph;    //    compute checksum in two parts (may not
        word checksum2;         //    have all of datagram built at once).
    } ph;
    struct _pkt {
        in_Header  in;
        udp_Header udp;
        int        data;
/*      longword maxsegopt; */
    } *pkt;
    byte *dp;
    in_Header *inp;
    udp_Header *udpp;

    word maxlen;
    int more_frags;
    word origlen = len;

    // S. Lawson - set Ethernet address if not set (possible if we were
    // a passive/broadcast socket
    if (memcmp(&s->hisethaddr, "\0\0\0\0\0\0", 6)==0) {
       /* check for broadcast */
       /* 2001.1.18 changed from -1 */
       if ( s->hisaddr == 0xffffffff || !s->hisaddr )
          memset( &s->hisethaddr, 0xff, sizeof( eth_address ));
       else if ( ! _arp_resolve(s->hisaddr, &s->hisethaddr, 0) )
          return( 0 );
    }

    pkt = (struct _pkt *)_eth_formatpacket(&s->hisethaddr, /*0x800*/ 8);

    if( offset ) {              // this is not the first fragment
        dp = (byte *) &pkt->udp;    // data goes right after IP header
    } else {
        dp = (byte *) &pkt->data;
        udpp = &pkt->udp;

        /* udp header */
        udpp->srcPort = intel16( s->myport );
        udpp->dstPort = intel16( s->hisport );
        udpp->checksum = 0;
        udpp->length = intel16( UDP_LENGTH + len );
    }
    inp = &pkt->in;

    memset( inp, 0, sizeof( in_Header ));

// S. Lawson - this needs changed to handle DHCP when using 576 MSS
#ifdef NOTUSED
    maxlen = _mss & 0xFFF8;             // make a multiple of 8
    if( !offset ) maxlen -= UDP_LENGTH; // note UDP_LENGTH is 8, so ok
#else
    maxlen = _mss - sizeof( in_Header ) - sizeof ( udp_Header );
    if (offset) {
       maxlen += sizeof (udp_Header);
       maxlen &= 0xFFF8;                // make a multiple of 8
    }
#endif

    if( len > maxlen ) {
        maxlen &= 0xFFF8;               // S. Lawson - multiple of 8
        len = maxlen;
        more_frags = 1;
    } else more_frags = 0;

    inp->length = intel16( sizeof(in_Header) +
                                     (offset ? 0 : UDP_LENGTH) + len );
    movmem(datap, dp, len );

    /* internet header */
    inp->ver = 4;
    inp->hdrlen = 5;
    inp->tos = 0;
/* inp->vht = 0x4500;*/   /* version 4, hdrlen 5, tos 0 */
 /* if offset non-zero, then is part of a prev datagram so don't incr ID */
    inp->identification = intel16( offset ? ip_id : ++ip_id );   /* was post inc */
//    inp->frag = 0;
    inp->frags = (offset ? intel16((offset + UDP_LENGTH) >> 3) : 0);
    if(more_frags) inp->frags |= IP_MF;
    inp->ttl = 254;
    inp->proto = UDP_PROTO;     /* udp */
/* inp->ttlProtocol = (250<<8) + 6; */
    inp->checksum = 0;
    inp->source = intel( s->myaddr );
    inp->destination = intel( s->hisaddr );
    inp->checksum = ~checksum( inp, sizeof(in_Header));


    /* compute udp checksum if desired */
    if(!offset) {  // only first of frags has UDP header for entire UDP dgram
        if ( s->sock_mode & UDP_MODE_NOCHK )
            udpp->checksum = 0;
        else {
            ph.ph.src = inp->source;    /* already INTELled */
            ph.ph.dst = inp->destination;
            ph.ph.mbz = 0;
            ph.ph.protocol = UDP_PROTO; /* udp */
            ph.ph.length = udpp->length;        /* already INTELled */

          /* can't use since may not have the whole dgram built at once */
//          ph.checksum = checksum(&pkt->udp, intel16(ph.length));
          /* this way handles it */
            ph.ph.checksum = checksum(&pkt->udp, UDP_LENGTH);
            ph.checksum2 = checksum(datap, origlen);

            udpp->checksum =  ~checksum(&ph, sizeof(ph));
        }
    }

    if (_dbugxmit) (*_dbugxmit)( (sock_type*)s, inp, udpp, 0 );
    _eth_send( intel16( inp->length ));

    return ( len );
}

/*
 * udp_read - read data from buffer, does large buffering
 */
static int udp_read( udp_Socket *s, byte *datap, int maxlen )
{
    int x;

    if (maxlen < 0) maxlen = MAXINT;
    if (( x = s->rdatalen ) > 0) {
        if ( x > maxlen ) x = maxlen;
        if ( x > 0 ) {
            if (datap) movmem( s->rdata, datap, x );
            if ( s->rdatalen -= x )
                movmem( s->rdata + x, s->rdata, s->rdatalen);
        }
    }
    return( x );
}

void _udp_cancel( in_Header *ip )
{
    int len;
    udp_Header *up;
    udp_Socket *s;

    /* match to a udp socket */
    len = in_GetHdrlenBytes(ip);
    up = (udp_Header *)((byte *)ip + len);      /* udp frame pointer */

    /* demux to active sockets */
    for ( s = udp_allsocs; s; s = s->next )
        if ( s->hisport != 0 &&
             intel16( up->dstPort ) == s->hisport &&
             intel16( up->srcPort ) == s->myport &&
             intel( ip->destination ) == s->hisaddr ) break;
    if ( !s ) {
        /* demux to passive sockets */
        for ( s = udp_allsocs; s; s = s->next )
            if ( s->hisport == 0 && intel16( up->dstPort ) == s->myport ) break;
    }
    if (s) {
        s->rdatalen = 0;
        s->ip_type = 0;
    }
}

void *_tcp_lookup( longword hisip, word hisport, word myport )
{
    tcp_Socket *s;
    for ( s = tcp_allsocs; s; s = s->next ) {
        if ( ( myport == s->myport ) &&         /* always unique under WATTCP */
             ( hisport == s->hisport ) &&
             ( hisip == s->hisaddr ))
                return( s );
    }
    return( NULL );
}

void _tcp_cancel( in_Header *ip, int code, char *msg, longword dummyip )
{
    static int in_icmp_redirect = 0;            // smart@actrix.gen.nz
    int len;
    tcp_Socket *s;
    tcp_Header *tp;

    len = in_GetHdrlenBytes(ip);        /* check work */

    tp = (tcp_Header *)((byte *)ip + len);      /* tcp frame pointer */

    /* demux to active sockets */
    for ( s = tcp_allsocs; s; s = s->next ) {
        if ( intel16( tp->srcPort) == s->myport &&
             intel16( tp->dstPort ) == s->hisport &&
             intel( ip->destination ) == s->hisaddr ) {
                switch (code) {
                    /* halt it */
                    case  1 : if (( s->stress ++ > s->rigid ) &&
                                  ( s->rigid < 100 )) {
                                  s->err_msg = (msg) ?
                                    msg : "ICMP closed connection";
                                  s->rdatalen = s->datalen = 0;
                                  s->unhappy = false;
                                  tcp_abort( s );
                /*      if (s->dataHandler) s->dataHandler(s, 0, -1); */
                                  break;
                              }
                              // follow through to next case

                    /* slow it down */
                    case  2 : s->cwindow = 1;
                              s->wwindow = 1;
                              s->rto <<= 2;
                              s->vj_sa <<= 2;
                              s->vj_sd <<= 2;
                              break;
                    /* icmp redirect for host */
                    case  5 : /* save his NEW network address */
                        /* Dummy is passed in NW form need to intel! */
                        /* This was a bug fixed QVS - smart@actrix.gen.nz */
                              if (!in_icmp_redirect)
                              {
                                  in_icmp_redirect = 1;
                                  _arp_resolve(intel(dummyip), &s->hisethaddr, 0);
                                  in_icmp_redirect = 0;
                              }
                              break;
                }
        }
    }
}

static int tcp_read( tcp_Socket *s, byte *datap, int maxlen )
{
    int x;
    long ldiff;                         // S. Lawson
    int diff;                           // S. Lawson

    if (maxlen < 0 ) maxlen = MAXINT;
    if (( x = s->rdatalen) > 0) {
        if ( x > maxlen ) x = maxlen;
        if ( x > 0 ) {
            if (datap) movmem( s->rdata, datap, x );
#ifdef NOTUSED  // S. Lawson - possible data fragment above
            if (( s->rdatalen -= x ) > 0 ) {
                movmem( s->rdata + x, s->rdata, s->rdatalen );
#else   // S. Lawson
            if (( s->rdatalen -= x ) > 0 || s->frag[0] != 0L) {
                diff=0;
                if (s->frag[0] != 0L) {
                   ldiff=s->frag[1] - s->acknum;
                   diff=abs((int) ldiff);
                }
                movmem( s->rdata + x, s->rdata, s->rdatalen + diff);
#endif
                tcp_sendsoon( s );   /* update the window */
            } else
                tcp_send( s, __LINE__ );      /* update window el-pronto */
        }
    } else if ( s->state == tcp_StateCLOSWT )
        tcp_close( s );
    return( x );
}

/*
 * Write data to a connection.
 * Returns number of bytes written, == 0 when connection is not in
 * established state.
 */
static int tcp_write( tcp_Socket *s, byte *dp, int len )
{
    int x;

    if (len < 0 ) len = MAXINT;
    /* no longer uses tcp_MaxData */
    if ( s->state != tcp_StateESTAB ) len = 0;
// S. Lawson - fixed per GV (behaves badly with user defined buffers)
//  if ( len > (x = s->maxrdatalen - s->datalen) ) len = x;
    if ( len > (x = tcp_MaxBufSize - s->datalen) ) len = x;

    if ( len > 0 ) {
        movmem( dp, s->data + s->datalen, len );

        s->datalen += len;
        s->unhappy = true;      /* redundant because we have outstanding data */
        s->datatimer = set_timeout( sock_data_timeout ); /* EE 99.08.23 */

        if ( s->sock_mode & TCP_LOCAL )
            s->sock_mode &= ~TCP_LOCAL;
        else {
            if ( s->sock_mode & TCP_MODE_NONAGLE ) {
                tcp_send( s, __LINE__ );
            } else {
                /* transmit if first data or reached MTU */
                /* not true MTU, but better than nothing */
                if (( s->datalen == len ) || ( s->datalen > (s->mss)/2 ))
                    tcp_send( s, __LINE__ );
                else
                    tcp_sendsoon( s );
            }
        }
    }

    return ( len );
}

/*
 * Send pending data
 */
static void tcp_Flush( tcp_Socket *s )
{
    if ( s->datalen > 0 ) {
        s->flags |= tcp_FlagPUSH;
        if (s->unacked == 0)            // S. Lawson - only if data not moving
           tcp_send(s, __LINE__);
    }
}

/*
 * Handler for incoming packets.
 */
static void udp_handler( in_Header *ip )
{
    udp_Header *up;
    tcp_PseudoHeader ph;

⌨️ 快捷键说明

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