home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / WATTCP / WNWATTCP.ZIP / SRC / PCTCP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-20  |  53.5 KB  |  1,995 lines

  1. #define DEBUG
  2. /*
  3.  *  PCTCP - the true worker of Waterloo TCP
  4.  *         - contains all opens, closes, major read/write routines and
  5.  *        basic IP handler for incomming packets
  6.  *      - NOTE: much of the TCP/UDP/IP layering is done at the data structure
  7.  *        level, not in separate routines or tasks
  8.  *
  9.  */
  10.  
  11. #include <copyright.h>
  12. #include <time.h>
  13. #include <stdio.h>
  14. #include <stdarg.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <mem.h>
  18. #include <dos.h>
  19.  
  20. #include "wattcp.h"
  21. #include "elib.h"
  22.  
  23. /* statics */
  24. static tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len);
  25.  
  26. #ifndef WINDOWS
  27. static char far *mono = 0xb0000000L;
  28. static char far *colour = 0xb8000000L;
  29. #endif
  30.  
  31. static initialized = 0;
  32. static void (*system_yield)() = NULL;
  33. void (*_dbugxmit)() = NULL;
  34. void (*_dbugrecv)() = NULL;
  35.  
  36. char *_hostname = "012345678901234567890123456789012345678901234567890";
  37.  
  38. word _mss = ETH_MSS;
  39.  
  40. char *_wattcp = WATTCP_C;
  41.  
  42. /*
  43.  * sock_yield - enable user defined yield function
  44.  */
  45. sock_yield( tcp_Socket *s, void (*fn)())
  46. {
  47.     if ( s )
  48.     s->usr_yield = fn;
  49.     else
  50.     system_yield = fn;
  51. }
  52.  
  53. /*
  54.  * sock_mode - set binary or ascii - affects sock_gets, sock_dataready
  55.  *         - set udp checksums
  56.  */
  57. sock_mode( sock_type *s, word mode )
  58. {
  59.      s->tcp.sock_mode = (s->tcp.sock_mode & 0xfffc) | mode;
  60. }
  61.  
  62. /*
  63.  * ip user level timer stuff
  64.  *   void ip_timer_init( void *s, int delayseconds )
  65.  *   int  ip_timer_expired( void *s )
  66.  *    - 0 if not expired
  67.  */
  68. unsigned long far *realclock = (unsigned long far *)0x0000046cL;
  69. #define MAXTICKS 0x1800b0L
  70.  
  71. void ip_timer_init( s , delayseconds )
  72. udp_Socket *s;
  73. int delayseconds;
  74. {
  75.     if (delayseconds)
  76.     s->usertimer = set_timeout( delayseconds );
  77.     else
  78.     s->usertimer = 0;
  79. }
  80.  
  81. int ip_timer_expired( s )
  82. udp_Socket *s;
  83. {
  84.     if (! s->usertimer)    /* cannot expire */
  85.     return( 0 );
  86.     return( chk_timeout( s->usertimer));
  87. }
  88. longword MsecClock()
  89. {
  90.     return( (*realclock) * 055L);
  91. }
  92. static long make_timeout( word timeout )
  93. {
  94.     if ( timeout ) return( set_timeout( timeout ));
  95.     return( 0 );
  96. }
  97. /*
  98.  * check_timeout - test agains timeout clock - account for overflow
  99.  */
  100. static int check_timeout( unsigned long timeout )
  101. {
  102.     if (timeout) return( chk_timeout( timeout ));
  103.     return( 0 );
  104. }
  105.  
  106. /*
  107.  * Local IP address
  108.  */
  109. longword my_ip_addr = 0L;    /* for external references */
  110. longword sin_mask = 0xfffffe00L;
  111. longword sin_gate = 0x0;
  112.  
  113.  
  114. /*
  115.  * IP identification numbers
  116.  */
  117.  
  118. static int ip_id = 0;            /* packet number */
  119. static int next_tcp_port = 1024;    /* auto incremented */
  120. static int next_udp_port = 1024;
  121. static tcp_Socket *tcp_allsocs = NULL;
  122. static udp_Socket *udp_allsocs = NULL;
  123.  
  124. /* Timer definitions */
  125. #define RETRAN_STRAT_TIME  1     /* in ticks - how often do we check retransmitter tables*/
  126. #define tcp_RETRANSMITTIME 3     /* interval at which retransmitter is called */
  127. #define tcp_LONGTIMEOUT 31       /* timeout for opens */
  128. #define tcp_TIMEOUT 13           /* timeout during a connection */
  129.  
  130. word debug_on = 0;
  131.  
  132. /*
  133.  * Shut down the card and all services
  134.  */
  135. tcp_shutdown()
  136. {
  137.     while (tcp_allsocs)
  138.     tcp_abort( tcp_allsocs );
  139.     _eth_release();
  140.     initialized = 0;
  141. }
  142.  
  143. /*
  144.  * tcp_Init - Initialize the tcp implementation
  145.  *        - may be called more than once without hurting
  146.  */
  147. tcp_init()
  148. {
  149.     extern int _arp_last_gateway;
  150.     extern int _last_nameserver;
  151.  
  152.     if (!initialized) {
  153.     /* initialize ethernet interface */
  154.     initialized = 1;
  155.     _eth_init();
  156.  
  157.     /* reset the various tables */
  158.     _arp_last_gateway = 0;    /* reset the gateway table */
  159.     _last_nameserver = 0;    /* reset the nameserver table */
  160.     _last_cookie = 0;    /* eat all remaining crumbs */
  161.     *_hostname = 0;        /* reset the host's name */
  162.  
  163.     if (!my_ip_addr) {
  164.         /* using our local reverse ethernet address thingamajig */
  165.         movmem( &_eth_addr[2], &my_ip_addr, 4 );
  166.     }
  167.     _eth_free( 0 );
  168.     next_udp_port = next_tcp_port = 1024 + ((*realclock >> 7 )& 0x1ff);
  169.     }
  170.     return 0;
  171. }
  172.  
  173. /*
  174.  * Checks for bugs in large model C compiler
  175.  */
  176. static largecheck( void *s, int size )
  177. {
  178.     if ( (word)(FP_OFF(s)) > (word)(-size)) {
  179. #ifndef WINDOWS
  180.     outs("ERROR: C compiler sock size error\n");
  181. #endif
  182.         exit( 3 );
  183.     }
  184. }
  185.  
  186. /* socket, localport, destaddress */
  187. int udp_open(s, lport, ina, port, datahandler)
  188. udp_Socket *s;
  189. longword ina;
  190. word lport, port;
  191. procref datahandler;
  192. {
  193.     udp_close( s );
  194.     largecheck( s, sizeof( udp_Socket ));
  195.     memset( s, 0, sizeof( udp_Socket ));
  196.     s->ip_type = UDP_PROTO;
  197.     if ( lport == 0 ) lport = ++next_udp_port;  /* get a nonzero port val */
  198.     s->myport = lport;
  199.  
  200.     /* check for broadcast */
  201.     if ( (long)(ina) == -1 || !ina )
  202.     memset( s->hisethaddr, 0xff, sizeof( eth_address ));
  203.     else if ( ! _arp_resolve(ina, &s->hisethaddr[0]) )
  204.     return( 0 );
  205.  
  206.     s->hisaddr = ina;
  207.     s->hisport = port;
  208.     s->dataHandler = datahandler;
  209.     s->usr_yield = system_yield;
  210.     s->safetysig = SAFETYUDP;
  211.     s->next = udp_allsocs;
  212.     udp_allsocs = s;
  213.     return( 1 );
  214. }
  215.  
  216. /*
  217.  * Actively open a TCP connection to a particular destination.
  218.  *    - 0 on error
  219.  */
  220. int tcp_open(tcp_Socket *s, word lport, longword ina, word port, procref datahandler)
  221. {
  222.     largecheck( s, sizeof( tcp_Socket ));   /* stack space warnings */
  223.     tcp_unthread(s);                        /* just in case not totally closed */
  224.  
  225.     memset( s, 0, sizeof( tcp_Socket));
  226.     s->ip_type = TCP_PROTO;
  227.     s->mss = _mss;
  228.     s->state = tcp_StateSYNSENT;
  229.     s->timeout = set_timeout( tcp_LONGTIMEOUT );
  230.     s->rmaxdatalen = tcp_MaxBufSize;
  231.     s->cwindow = 1;
  232.     s->wwindow = 0;     /* slow start VJ algorithm */
  233.     s->vj_sa = 4;      /* about 250 ms */
  234.     if ( lport == 0 ) lport = ++next_tcp_port;  /* get a nonzero port val */
  235.     s->myport = lport;
  236.     if ( ! _arp_resolve(ina, &s->hisethaddr[0]) )
  237.     return( 0 );
  238.  
  239.     s->hisaddr = ina;
  240.     s->hisport = port;
  241.     s->seqnum = intel( set_timeout( 1 )) & 0xffff0000;
  242.     s->datalen = 0;
  243.     s->flags = tcp_FlagSYN;
  244.     s->unhappy = true;
  245.     s->dataHandler = datahandler;
  246.     s->usr_yield = system_yield;
  247.  
  248.     s->safetysig = SAFETYTCP;       /* insert into chain */
  249.     s->next = tcp_allsocs;
  250.     tcp_allsocs = s;
  251.  
  252.     s->rtt_delay = s->rtt_smooth = 18;    /* one second startup */
  253.     tcp_send(s, __LINE__ );
  254.     return( 1 );
  255. }
  256.  
  257. /*
  258.  * Passive open: listen for a connection on a particular port
  259.  */
  260. tcp_listen(tcp_Socket *s, word lport, longword ina, word port, procref datahandler, word timeout)
  261. {
  262.     largecheck( s, sizeof( tcp_Socket ));
  263.     tcp_unthread(s);                        /* just in case not totally closed */
  264.     memset( s, 0, sizeof( tcp_Socket));
  265.     s->ip_type = TCP_PROTO;
  266.     s->mss = _mss;
  267.     s->rmaxdatalen = tcp_MaxBufSize;
  268.     s->cwindow = 1;
  269.     s->wwindow = 0;     /* slow start VJ algorithm */
  270.     s->vj_sa = 36;      /* about 250 ms */
  271.  
  272.     s->state = tcp_StateLISTEN;
  273.     if ( !timeout ) s->timeout = 0; /* forever... */
  274.     else s->timeout = set_timeout( timeout );
  275.     s->myport = lport;
  276.     s->hisport = port;
  277.     s->hisaddr = ina;
  278.     s->seqnum = intel( (word)(s));
  279.     s->datalen = 0;
  280.     s->flags = 0;
  281.     s->unhappy = false;
  282.     s->dataHandler = datahandler;
  283.     s->usr_yield = system_yield;
  284.  
  285.     s->safetysig = SAFETYTCP;       /* insert into chain */
  286.     s->next = tcp_allsocs;
  287.     tcp_allsocs = s;
  288.  
  289.     return( 1 );
  290. }
  291.  
  292.  
  293. static udp_close(ds)
  294. udp_Socket *ds;
  295. {
  296.     udp_Socket *s, **sp;
  297.  
  298.     sp = &udp_allsocs;
  299.     for (;;) {
  300.         s = *sp;
  301.         if ( s == ds ) {
  302.             *sp = s->next;
  303.             break;
  304.         }
  305.     if ( !s ) break;
  306.     if ( ! s->err_msg ) s->err_msg = "UDP Close called";
  307.     sp = &s->next;
  308.     }
  309. }
  310.  
  311. /*
  312.  * Send a FIN on a particular port -- only works if it is open
  313.  *   Must still allow receives
  314.  */
  315. static tcp_close(tcp_Socket *s)
  316. {
  317.     if ( s->ip_type != TCP_PROTO )
  318.     return;
  319.     if ( s->state == tcp_StateESTAB ||
  320.          s->state == tcp_StateESTCL ||
  321.          s->state == tcp_StateSYNREC ) {
  322.  
  323.         if ( s->datalen ) {     /* must first flush all data */
  324.             s->flags |= tcp_FlagPUSH | tcp_FlagACK;
  325.             if ( s->state < tcp_StateESTCL ) {
  326.                 s->state = tcp_StateESTCL;
  327.                 tcp_sendsoon( s );
  328.             }
  329.         } else { /* really closing */
  330.             s->flags = tcp_FlagACK | tcp_FlagFIN;
  331.             if (!s->err_msg)
  332.                 s->err_msg = "Connection closed normally";
  333.             s->state = tcp_StateFINWT1;
  334.             s->timeout = set_timeout( 4 ); /* should be a pretty lengthy time */
  335.             tcp_send( s, __LINE__ );
  336.         }
  337.         s->unhappy = true;
  338.     } else if (s->state == tcp_StateCLOSWT ) {
  339.         /* need to ack the fin and get on with it */
  340.         s->state = tcp_StateLASTACK;
  341.         s->flags |= tcp_FlagFIN;
  342.         tcp_send( s, __LINE__ );
  343.         s->unhappy = true;
  344.     }
  345. }
  346.  
  347. /*
  348.  * Abort a tcp connection
  349.  */
  350. static tcp_abort(tcp_Socket *s)
  351. {
  352.     if (!s->err_msg) s->err_msg = "TCP_ABORT";
  353.     if ( s->state != tcp_StateLISTEN && s->state != tcp_StateCLOSED ) {
  354.         s->flags = tcp_FlagRST  | tcp_FlagACK ;
  355.         s->unhappy = true;
  356.         tcp_send(s, __LINE__);
  357.     }
  358.     s->unhappy = false;
  359.     s->datalen = 0;
  360.     s->state = tcp_StateCLOSED;
  361. /*    if (s->dataHandler) s->dataHandler(s, 0, -1); */
  362.     tcp_unthread(s);
  363. }
  364.  
  365. void sock_abort(tcp_Socket *s )
  366. {
  367.     if ( s->ip_type == TCP_PROTO )
  368.     tcp_abort( s );
  369.     else
  370.     udp_close( s );
  371. }
  372. /*
  373.  * tcp_sendsoon - schedule a transmission pretty soon
  374.  *        - this one has an imperfection at midnight, but it
  375.  *          is not significant to the connection performance
  376.  */
  377. tcp_sendsoon(tcp_Socket *s )
  378. {
  379.     longword temp;
  380.     if (s->ip_type == TCP_PROTO ) {
  381.     temp = set_ttimeout( 1 );
  382.         if ( temp == s->rtt_time && s->rto < 2 && s->recent == 0 ) {
  383.             s->karn_count = 0;
  384.             tcp_send( s, __LINE__ );
  385.             s->recent = 1;
  386.             return;
  387.         }
  388.         if ((s->unhappy || s->datalen > 0 || s->karn_count == 1)
  389.           && (s->rtt_time < temp ))
  390.             return;
  391.  
  392.         s->rtt_time = set_ttimeout( 1 + (s->rto >> 4) );
  393.     s->karn_count = 1;
  394.     }
  395. }
  396.  
  397. /*
  398.  * Retransmitter - called periodically to perform tcp retransmissions
  399.  */
  400. static longword retran_strat = 0L; /* timeout retran strategy */
  401. static tcp_Retransmitter()
  402. {
  403.     tcp_Socket *s;
  404.  
  405.     /* only do this once per RETRAN_STRAT_TIME milliseconds */
  406.     if ( !chk_timeout( retran_strat ))
  407.     return;
  408.     retran_strat = set_ttimeout( RETRAN_STRAT_TIME );
  409.  
  410.     for ( s = tcp_allsocs; s; s = s->next ) {
  411.         if ( s->datalen > 0 || s->unhappy || s->karn_count == 1 ) {
  412.         /* retransmission strategy */
  413.         if ( chk_timeout( s->rtt_time)) {
  414.                 if ( s->karn_count == 0 ) { /* if really did timeout */
  415. #ifdef DEBUG
  416.     if(debug_on >1) printf("regular retran TO set unacked back to 0 from %u\n", s->unacked);
  417. #endif DEBUG
  418.             s->karn_count = 2;
  419.  
  420.                     s->unacked = 0;
  421.                     /* use the backed off rto - implied, no code necessary */
  422.                     /* reduce the transmit window */
  423.                     s->cwindow =  ((s->cwindow + 1) * 3) >> 2;
  424.                     s->wwindow = 0;
  425.                 }
  426.                 tcp_send(s, __LINE__);
  427.         }
  428.     }
  429.     /* handle inactive tcp timeouts */
  430.         if ( sock_inactive && s->inactive_to ) {
  431.             if ( chk_timeout( s->inactive_to)) {
  432.                 /* this baby has timed out */
  433.                 s->err_msg = "Connection timed out - no activity";
  434.                 sock_close( s );
  435.             }
  436.         }
  437.         if ( s->timeout && chk_timeout( s->timeout)) {
  438.         if ( s->state == tcp_StateTIMEWT ) {
  439.         s->state = tcp_StateCLOSED;
  440.         tcp_unthread(s);
  441.                 break;
  442.             } else if (s->state != tcp_StateESTAB && s->state != tcp_StateESTCL ) {
  443.         s->err_msg = "Timeout, aborting";
  444.         tcp_abort(s);
  445.                 break;
  446.         }
  447.     }
  448.     }
  449. }
  450.  
  451. /*
  452.  * Unthread a socket from the tcp socket list, if it's there
  453.  */
  454. static tcp_unthread(tcp_Socket *ds)
  455. {
  456.     tcp_Socket *s, **sp;
  457.  
  458.     if (!ds->rdatalen || (ds->state > tcp_StateESTCL))
  459.     ds->ip_type = 0;    /* fail io */
  460.     ds->state = tcp_StateCLOSED;   /* tcp_tick needs this */
  461.     sp = &tcp_allsocs;
  462.     for (;;) {
  463.     s = *sp;
  464.     if ( s == ds ) {
  465.         *sp = s->next;
  466.             continue;           /* unthread multiple copies if necessary */
  467.     }
  468.     if ( !s ) break;
  469.     sp = &s->next;
  470.     }
  471. }
  472.  
  473. /*
  474.  * tcp_tick - called periodically by user application
  475.  *        - returns 1 when our socket closes
  476.  *        - called with socket parameter or NULL
  477.  */
  478. tcp_tick( sock_type *s )
  479. {
  480.     in_Header *ip;
  481.     static longword timeout = 0;
  482.     static longword start = 0;
  483.  
  484.     int x;
  485.     int packettype;
  486.  
  487.     /* finish off dead sockets */
  488.     if ( s ) {
  489.         if (( s->tcp.ip_type == TCP_PROTO ) &&
  490.             ( s->tcp.state == tcp_StateCLOSED ) &&
  491.             ( s->tcp.rdatalen == 0 )) {
  492.                 tcp_unthread(s);
  493.         s->tcp.ip_type = 0;
  494.         }
  495.     }
  496.  
  497.  
  498.     /* plan our next retransmit */
  499.  
  500.     if ( !timeout )
  501.     timeout = make_timeout( tcp_RETRANSMITTIME );
  502.  
  503.     while ( ip = _eth_arrived( &packettype ) ) {
  504.     start = *realclock;
  505.  
  506.     switch ( packettype ) {
  507.     case /*0x800*/ 0x008 :
  508.         /* do IP */
  509.         if ( checksum(ip, in_GetHdrlenBytes(ip)) == 0xffff ) {
  510.         if ( !my_ip_addr || (intel( ip->destination ) == my_ip_addr)){
  511.             switch ( ip->proto ) {
  512.             case TCP_PROTO :
  513.             tcp_handler(ip);
  514.             break;
  515.             case UDP_PROTO :
  516.             udp_handler(ip);
  517.             break;
  518.             case ICMP_PROTO :
  519.             icmp_handler(ip);
  520.             break;
  521.             }
  522.         }
  523. #ifdef WINDOWS
  524.     /* nothing */
  525. #else
  526.         } else  {
  527.         if (debug_on)
  528.             outs("IP Received BAD Checksum \n\r");
  529. #endif
  530.         }
  531.         break;
  532.     case /*0x806*/ 0x608 :
  533.             /* do arp */
  534.         _arp_handler(ip);
  535.         break;
  536.     }
  537.     if (ip) _eth_free(ip);
  538.  
  539.     continue;
  540.     }
  541. /*
  542.     x = *realclock - start;
  543.     timeout -= x;
  544. */
  545.     /* check for our outstanding packets */
  546.     tcp_Retransmitter();
  547.  
  548.     return( (s) ? s->udp.ip_type : 0 );
  549. }
  550.  
  551. tcp_set_debug_state( x )
  552. int x;
  553. {
  554.     debug_on = x;
  555. }
  556.  
  557. /* returns 1 if connection is established */
  558. int tcp_established(tcp_Socket *s)
  559. {
  560.     return( s->state == tcp_StateESTAB || s->state == tcp_StateESTCL
  561.         || s->state == tcp_StateCLOSWT );
  562. }
  563.  
  564.  
  565. static udp_Write(s, datap, len)
  566. udp_Socket *s;
  567. byte *datap;
  568. int len;
  569. {
  570.     tcp_PseudoHeader ph;
  571.     struct _pkt {
  572.     in_Header  in;
  573.     udp_Header udp;
  574.     int       data;
  575. /*    longword maxsegopt; */
  576.     } *pkt;
  577.     byte *dp;
  578.     in_Header *inp;
  579.     udp_Header *udpp;
  580.  
  581.     pkt = (struct _pkt *)_eth_formatpacket(&s->hisethaddr[0], /*0x800*/ 8);
  582.     dp = &pkt->data;
  583.     inp = &pkt->in;
  584.     udpp = &pkt->udp;
  585.  
  586.     inp->length = intel16( sizeof(in_Header) + UDP_LENGTH + len );
  587.  
  588.     /* udp header */
  589.     udpp->srcPort = intel16( s->myport );
  590.     udpp->dstPort = intel16( s->hisport );
  591.     udpp->checksum = 0;
  592.     udpp->length = intel16( UDP_LENGTH + len );
  593.     movmem(datap, dp, len );
  594.  
  595.     /* internet header */
  596.     inp->ver = 4;
  597.     inp->hdrlen = 5;
  598.     inp->tos = 0;
  599. /* inp->vht = 0x4500;*/   /* version 4, hdrlen 5, tos 0 */
  600.     inp->identification = intel16( ++ip_id );   /* was post inc */
  601.     inp->frag = 0;
  602.     inp->ttl = 254;
  603.     inp->proto = UDP_PROTO;    /* udp */
  604. /* inp->ttlProtocol = (250<<8) + 6; */
  605.     inp->checksum = 0;
  606.     inp->source = intel( my_ip_addr );
  607.     inp->destination = intel( s->hisaddr );
  608.     inp->checksum = ~checksum( inp, sizeof(in_Header))/* 0*/; /* Watstar */
  609.  
  610.  
  611.     /* compute udp checksum if desired */
  612.     if ( s->sock_mode & UDP_MODE_NOCHK )
  613.     udpp->checksum = 0;
  614.     else {
  615.     ph.src = inp->source;    /* already INTELled */
  616.     ph.dst = inp->destination;
  617.     ph.mbz = 0;
  618.     ph.protocol = UDP_PROTO;    /* udp */
  619.     ph.length = udpp->length;    /* already INTELled */
  620.  
  621.     ph.checksum = checksum(&pkt->udp, intel16(ph.length));
  622.     udpp->checksum =  ~checksum(&ph, sizeof(ph));
  623.     }
  624.  
  625.     if (_dbugxmit) (*_dbugxmit)(s,inp,udpp);
  626.     _eth_send( intel16( inp->length ));
  627.  
  628.     return ( len );
  629. }
  630.  
  631. /*
  632.  * udp_read - read data from buffer, does large buffering
  633.  */
  634. static int udp_read(s, datap, maxlen)
  635. udp_Socket *s;
  636. byte *datap;
  637. int maxlen;
  638. {
  639.     int x;
  640.  
  641.     if (( x = s->rdatalen ) > 0) {
  642.     if ( x > maxlen ) x = maxlen;
  643.     if ( x > 0 ) {
  644.         movmem( s->rdata, datap, x );
  645.         if ( s->rdatalen -= x )
  646.                 movmem( s->rdata + x, s->rdata, s->rdatalen);
  647.     }
  648.     }
  649.     return( x );
  650. }
  651.  
  652. _udp_cancel( in_Header *ip )
  653. {
  654.     int len;
  655.     udp_Header *up;
  656.     udp_Socket *s;
  657.  
  658.     /* match to a udp socket */
  659.     len = in_GetHdrlenBytes(ip);
  660.     up = (udp_Header *)((byte *)ip + len);    /* udp frame pointer */
  661.  
  662.     /* demux to active sockets */
  663.     for ( s = udp_allsocs; s; s = s->next )
  664.         if ( s->hisport != 0 &&
  665.          intel16( up->dstPort ) == s->myport &&
  666.          intel16( up->srcPort ) == s->hisport &&
  667.          intel( ip->source ) == s->hisaddr ) break;
  668.     if ( !s ) {
  669.     /* demux to passive sockets */
  670.     for ( s = udp_allsocs; s; s = s->next )
  671.         if ( s->hisport == 0 && intel16( up->dstPort ) == s->myport ) break;
  672.     }
  673.     if (s) {
  674.         s->rdatalen = 0;
  675.     s->ip_type = 0;
  676.     }
  677. }
  678.  
  679. _tcp_cancel(in_Header *ip, int code)
  680. {
  681.     int len;
  682.     tcp_Socket *s;
  683.     tcp_Header *tp;
  684.  
  685.     len = in_GetHdrlenBytes(ip);    /* check work */
  686.  
  687.     tp = (tcp_Header *)((byte *)ip + len);    /* tcp frame pointer */
  688.  
  689.     /* demux to active sockets */
  690.     for ( s = tcp_allsocs; s; s = s->next ) {
  691.         if ( intel16( tp->dstPort ) == s->myport &&
  692.          intel16( tp->srcPort ) == s->hisport &&
  693.              intel( ip->source ) == s->hisaddr ) {
  694.                 switch (code) {
  695.                     /* halt it */
  696.                     case  1 : s->err_msg = "ICMP closed connection";
  697.                               s->rdatalen = s->datalen = 0;
  698.                               s->unhappy = false;
  699.                               s->state = tcp_StateCLOSED;
  700.                 /*      if (s->dataHandler) s->dataHandler(s, 0, -1); */
  701.                               break;
  702.                     /* slow it down */
  703.                     case  2 : s->cwindow = 1;
  704.                               s->wwindow = 1;
  705.                               s->rto <<= 2;
  706.                               s->vj_sa <<= 2;
  707.                               s->vj_sd <<= 2;
  708.                               break;
  709.                 }
  710.         }
  711.     }
  712.  
  713. }
  714.  
  715. static int tcp_read(tcp_Socket *s, byte *datap, int maxlen)
  716. {
  717.     int x;
  718.  
  719.     if (( x = s->rdatalen) > 0) {
  720.     if ( x > maxlen ) x = maxlen;
  721.         if ( x > 0 ) {
  722.             movmem( s->rdata, datap, x );
  723.             if (( s->rdatalen -= x ) > 0 ) {
  724.                 movmem( s->rdata + x, s->rdata, s->rdatalen );
  725.                 tcp_sendsoon( s );   /* update the window */
  726.             } else
  727.                 tcp_send( s, __LINE__ );      /* update window el-pronto */
  728.     }
  729.     } else if ( s->state == tcp_StateCLOSWT )
  730.         tcp_close( s );
  731.     return( x );
  732. }
  733.  
  734. /*
  735.  * Write data to a connection.
  736.  * Returns number of bytes written, == 0 when connection is not in
  737.  * established state.
  738.  */
  739. static tcp_Write(tcp_Socket *s, byte *dp, int len)
  740. {
  741.     int x;
  742.  
  743.     /* no longer uses tcp_MaxData */
  744.     if ( s->state != tcp_StateESTAB ) len = 0;
  745.     if ( len > (x = tcp_MaxBufSize - s->datalen) ) len = x;
  746.     if ( len > 0 ) {
  747.         movmem( dp, s->data + s->datalen, len );
  748.  
  749.     s->datalen += len;
  750.     s->unhappy = true;    /* redundant because we have outstanding data */
  751.  
  752.     if ( s->sock_mode & TCP_MODE_NONAGLE ) {
  753.             tcp_send( s, __LINE__ );
  754.     } else {
  755.         /* transmit if first data or reached MTU */
  756.         /* not true MTU, but better than nothing */
  757.         if (( s->datalen == len ) || ( s->datalen > (s->mss)/2 ))
  758.                 tcp_send( s, __LINE__ );
  759.             else
  760.                 tcp_sendsoon( s );
  761.     }
  762.     }
  763.  
  764.     return ( len );
  765. }
  766.  
  767. /*
  768.  * Send pending data
  769.  */
  770. static tcp_Flush(tcp_Socket *s)
  771. {
  772.     if ( s->datalen > 0 ) {
  773.         s->flags |= tcp_FlagPUSH;
  774.         tcp_send(s, __LINE__);
  775.     }
  776. }
  777.  
  778. /*
  779.  * Handler for incoming packets.
  780.  */
  781. static udp_handler(in_Header *ip)
  782. {
  783.     udp_Header *up;
  784.     tcp_PseudoHeader ph;
  785.     word len;
  786.     byte *dp;
  787.     udp_Socket *s;
  788.  
  789.  
  790.     len = in_GetHdrlenBytes(ip);
  791.     up = (udp_Header *)((byte *)ip + len);    /* udp segment pointer */
  792.     len = intel16( up->length );
  793.  
  794.     /* demux to active sockets */
  795.     for ( s = udp_allsocs; s; s = s->next ) {
  796.         if ( s->safetysig != SAFETYUDP ) {
  797. #ifdef WINDOWS
  798.     /* nothing */
  799. #else
  800.         if (debug_on) outs("chain error in udp\r\n");
  801. #endif
  802.         }
  803.         if ( s->hisport != 0 &&
  804.          intel16( up->dstPort ) == s->myport &&
  805.          intel16( up->srcPort ) == s->hisport &&
  806.          intel( ip->source ) == s->hisaddr ) break;
  807.     }
  808.     if (_dbugrecv) (*_dbugrecv)(s,ip,up);
  809.     if ( !s ) {
  810.         /* demux to passive sockets */
  811.     for ( s = udp_allsocs; s; s = s->next )
  812.         if ( s->hisaddr == 0 && intel16( up->dstPort ) == s->myport ) {
  813.         if (_arp_resolve(intel(ip->source), &s->hisethaddr[0])) {
  814.             s->hisaddr = intel( ip->source );
  815.             s->hisport = intel16( up->srcPort );
  816.         }
  817.         break;
  818.         }
  819.     }
  820.     if ( !s ) {
  821.     /* demux to broadcast sockets */
  822.     for ( s = udp_allsocs; s; s = s->next )
  823.         if ( s->hisaddr == 0xffffffff && intel16( up->dstPort ) == s->myport ) break;
  824.     }
  825.  
  826.     if ( !s ) {
  827. #ifdef WINDOWS
  828.     /* nothing */
  829. #else
  830.     if (debug_on) outs("discarding...");
  831. #endif
  832.     return;
  833.     }
  834.  
  835.     if ( up->checksum ) {
  836.     ph.src = ip->source;    /* already INTELled */
  837.     ph.dst = ip->destination;
  838.     ph.mbz = 0;
  839.     ph.protocol = UDP_PROTO;
  840.     ph.length = up->length;
  841.     ph.checksum =  checksum(up, len);
  842.     if (checksum(&ph, sizeof( tcp_PseudoHeader)) != 0xffff)
  843.         return;
  844.     }
  845.  
  846.     /* process user data */
  847.     if ( (len -= UDP_LENGTH ) > 0) {
  848.     dp = (byte *)( up );
  849.     if (s->dataHandler) s->dataHandler( s, &dp[ UDP_LENGTH ], len , &ph);
  850.     else {
  851.         if (len > tcp_MaxBufSize ) len = tcp_MaxBufSize;
  852.         movmem( &dp[ UDP_LENGTH ], s->rdata, len );
  853.         s->rdatalen = len;
  854.     }
  855.     }
  856. }
  857.  
  858. static tcp_handler(in_Header *ip)
  859. {
  860.     tcp_Header *tp;
  861.     tcp_PseudoHeader ph;
  862.     int len;
  863.     byte *dp;
  864.     int diff;
  865.     tcp_Socket *s;
  866.     word flags;
  867.     long diffticks, ldiff;    /* must be signed */
  868.     long scheduleto;
  869.  
  870.  
  871.  
  872.     len = in_GetHdrlenBytes(ip);
  873.     len = intel16( ip->length ) - len;        /* len of tcp data */
  874.  
  875.     len = in_GetHdrlenBytes(ip);
  876.     tp = (tcp_Header *)((byte *)ip + len);    /* tcp frame pointer */
  877.     len = intel16( ip->length ) - len;        /* len of tcp data */
  878.     flags = intel16( tp->flags );
  879.  
  880.     if (debug_on > 1) {
  881. #ifndef WINDOWS
  882.             mono[160]++;
  883.             colour[160]++;
  884.             mono[162] = colour[162] = (flags & tcp_FlagSYN) ? 'S' : ' ';
  885.             mono[164] = colour[164] = (flags & tcp_FlagACK) ? 'A' : ' ';
  886.             mono[166] = colour[166] = (flags & tcp_FlagFIN) ? 'F' : ' ';
  887.             mono[168] = colour[168] = (flags & tcp_FlagRST) ? 'R' : ' ';
  888. #endif
  889.         }
  890.  
  891.  
  892.     /* demux to active sockets */
  893.     for ( s = tcp_allsocs; s; s = s->next ) {
  894.         if ( s->safetysig != SAFETYTCP ) {
  895. #ifdef WINDOWS
  896.     /* nothing */
  897. #else
  898.         if (debug_on) outs("chain error in tcp\r\n");
  899. #endif
  900.         }
  901.     if ( s->hisport != 0 &&
  902.          intel16( tp->dstPort ) == s->myport &&
  903.          intel16( tp->srcPort ) == s->hisport &&
  904.          intel( ip->source ) == s->hisaddr ) break;
  905.     }
  906.     if ( !s && (flags & tcp_FlagSYN)) {
  907.     /* demux to passive sockets, must be a new session */
  908.     for ( s = tcp_allsocs; s; s = s->next )
  909.         if ((s->hisport == 0) && (intel16( tp->dstPort ) == s->myport ))
  910.         break;
  911.     }
  912.  
  913.  
  914.     if (_dbugrecv) (*_dbugrecv)(s,ip,tp);
  915.     if ( !s ) {
  916.         if (!(flags & tcp_FlagRST)) tcp_rst( ip, tp );
  917.     return;
  918.     }
  919.  
  920.  
  921.     /* save his ethernet address */
  922.     movmem(&((((eth_Header *)ip) - 1)->source[0]), &s->hisethaddr[0], sizeof(eth_address));
  923.  
  924.     ph.src = ip->source;    /* already INTELled */
  925.     ph.dst = ip->destination;
  926.     ph.mbz = 0;
  927.     ph.protocol = TCP_PROTO;
  928.     ph.length = intel16( len );
  929.     ph.checksum =  checksum(tp, len);
  930.     if ( checksum(&ph, sizeof(ph)) != 0xffff ) {
  931. #ifdef WINDOWS
  932.     /* nothing */
  933. #else
  934.      if (debug_on) outs("bad tcp checksum \n\r");
  935. #endif
  936.  
  937.          /* tester */
  938.          ph.checksum =  checksum(tp, len);
  939.          checksum(&ph, sizeof(ph));
  940.  
  941.          tcp_sendsoon( s );
  942.      return;
  943.     }
  944.  
  945. /* reset code */
  946.     if ( flags & tcp_FlagRST ) {
  947. #ifdef WINDOWS
  948.     /* nothing */
  949. #else
  950.     if (debug_on) outs("\7\7\7\7\7\7\7connection reset\n");
  951. #endif
  952.         s->rdatalen = s->datalen = 0;
  953.         s->err_msg = "Remote reset connection";
  954.     s->state = tcp_StateCLOSED;
  955. /*    if (s->dataHandler) s->dataHandler(s, 0, -1); */
  956.     tcp_unthread(s);
  957.     return;
  958.     }
  959.  
  960.     if ( sock_inactive )
  961.         s->inactive_to = set_timeout( sock_inactive );
  962.  
  963.  
  964.     /* update our retransmission stuff */
  965.     /* new algorithms */
  966.     if (s->karn_count == 2) {
  967.         s->karn_count = 0;
  968. #ifdef DEBUG
  969.         if (debug_on > 1 ) printf("finally got it safely zapped from %u to ????\n\r",s->unacked);
  970. #endif /* DEBUG */
  971.     } else {
  972.         if ( s->vj_last ) {
  973.             /* unnecessary to use unhappy || s->datalen ) */
  974.             if ((diffticks = set_ttimeout( 0 ) - s->vj_last) >= 0 ) {
  975.                 /* we ignore the overnight case */
  976.                 diffticks -= (longword)( s->vj_sa >> 3 );
  977.                 s->vj_sa += (int)diffticks;
  978.                 if (diffticks < 0)
  979.                     diffticks = - diffticks;
  980.                 diffticks -= (s->vj_sd >> 2);
  981.                 s->vj_sd += (int)diffticks;
  982.                 if (s->vj_sa > MAXVJSA) s->vj_sa = MAXVJSA;
  983.                 if (s->vj_sd > MAXVJSD) s->vj_sd = MAXVJSD;
  984.             }
  985.             /* only recompute rtt hence rto after success */
  986.             s->rto = 1 + ((s->vj_sa >> 2) + (s->vj_sd)) >> 1 ;
  987. #ifdef DEBUG
  988.             if (debug_on > 1 ) printf("rto  %u  sa  %u  sd  %u   cwindow %u  wwindow %u  unacked %u\n",
  989.                 s->rto, s->vj_sa, s->vj_sd, s->cwindow, s->wwindow, s->unacked );
  990. #endif /* DEBUG */
  991.     }
  992.         s->karn_count = 0;
  993.         if ( s->wwindow++ >= s->cwindow ) {
  994.             s->cwindow++;
  995.             s->wwindow = 0;
  996.         }
  997.     }
  998.     /* all new */
  999.     scheduleto = set_ttimeout( s->rto + 2 );
  1000.     if ( s->rtt_time < scheduleto ) s->rtt_time = scheduleto;
  1001.  
  1002.  
  1003.     switch ( s->state ) {
  1004.  
  1005.     case tcp_StateLISTEN:    /* accepting SYNs */
  1006.         if ( flags & tcp_FlagSYN ) {
  1007.         s->acknum = intel( tp->seqnum ) + 1;
  1008.         s->hisport = intel16( tp->srcPort );
  1009.         s->hisaddr = intel( ip->source );
  1010.         s->flags = tcp_FlagSYN | tcp_FlagACK;
  1011.                 s->state = tcp_StateSYNREC;
  1012.         s->unhappy = true;
  1013.                 tcp_send(s, __LINE__);    /* we must respond immediately */
  1014.  
  1015.         s->timeout = set_timeout( tcp_TIMEOUT );
  1016.         } else
  1017.         tcp_rst( ip , tp );  /* send a reset */
  1018.  
  1019.         return( 1 );
  1020.         break;      /* unreachable */
  1021.  
  1022.     case tcp_StateSYNSENT:    /* added ACK Section */
  1023.         if ( flags & tcp_FlagSYN ) {
  1024.         s->flags = tcp_FlagACK;
  1025.         s->timeout = set_timeout( tcp_TIMEOUT );
  1026.  
  1027.         /* FlagACK means connection established, else SYNREC */
  1028.         if ( flags & tcp_FlagACK) {
  1029.             /* but is it for the correct session ? */
  1030.             if (tp->acknum == intel(s->seqnum + 1)) {
  1031.             s->state = tcp_StateESTAB;
  1032.             s->seqnum++;    /* good increment */
  1033.             s->acknum = intel( tp->seqnum  ) + 1;    /* 32 bits */
  1034.             tcp_ProcessData(s, tp, len);    /* someone may try it */
  1035.                         s->unhappy = true;              /* they must be told */
  1036.             } else {
  1037.             /* wrong ack, force a RST and resend SYN soon*/
  1038.             s->flags = tcp_FlagRST;
  1039.             s->unhappy = true;
  1040.                         tcp_send( s, __LINE__ );
  1041.                         s->flags = tcp_FlagSYN;
  1042.                         tcp_send( s, __LINE__ );
  1043.             }
  1044.         } else {
  1045.             s->acknum++;
  1046.             s->state = tcp_StateSYNREC;
  1047.             return( 1 );
  1048.         }
  1049.             } else
  1050.                 tcp_rst( ip, tp );
  1051.         break;
  1052.  
  1053.     case tcp_StateSYNREC:    /* recSYNSENT, sentACK, waiting  EST */
  1054.         if ( flags & tcp_FlagSYN ) {
  1055.         s->flags = tcp_FlagSYN | tcp_FlagACK;
  1056.         s->unhappy = true;
  1057.                 tcp_send(s, __LINE__);
  1058.         s->timeout = set_timeout( tcp_TIMEOUT );
  1059.         return( 1 );
  1060.         }
  1061.         if ( (flags & tcp_FlagACK) && (intel( tp->acknum ) == (s->seqnum + 1))) {
  1062.                 s->window = intel16( tp->window );
  1063.         s->flags = tcp_FlagACK;
  1064.                 s->state = tcp_StateESTAB;
  1065.                 s->seqnum++;
  1066.                 s->timeout = 0;     /* never timeout */
  1067.                 s->unhappy = false;
  1068.         return( 1 );
  1069.         }
  1070.  
  1071.         break;
  1072.     case tcp_StateESTAB:
  1073.         case tcp_StateESTCL:
  1074.         case tcp_StateCLOSWT:
  1075.  
  1076.         if ( !(flags & tcp_FlagACK)) return;  /* must ack somthing */
  1077.             if ( flags & tcp_FlagSYN ) {
  1078.                 tcp_rst( ip , tp );
  1079.                 return;
  1080.             }
  1081.         s->timeout = 0l;    /* we do not timeout at this point */
  1082.  
  1083.         /* process ack value in packet - but only if it falls
  1084.          * within current window */
  1085.  
  1086.         ldiff = intel( tp->acknum ) - s->seqnum;
  1087.         diff = (int) ldiff;
  1088.  
  1089.             if ( ldiff >= 0 && diff <= s->datalen ) {
  1090.         s->datalen -= diff;
  1091.                 s->unacked -= diff;
  1092.                 if (s->datalen < 0) s->datalen = 0; /* remote proto error */
  1093.                 if ( s->queuelen ) {
  1094.                     s->queue += diff;
  1095.                     s->queuelen -= diff;
  1096.                 } else
  1097.                     movmem(s->data + diff, s->data, s->datalen );
  1098.         s->seqnum += ldiff;
  1099.             } else {
  1100. #ifdef DEBUG
  1101.     if(debug_on >1) printf("tcphandler confused so set unacked back to 0 from %u\n",s->unacked);
  1102. #endif DEBUG
  1103.                 s->unacked = 0;
  1104.             }
  1105.             if (s->unacked < 0) s->unacked = 0;
  1106.  
  1107.         s->flags = tcp_FlagACK;
  1108.         tcp_ProcessData(s, tp, len);
  1109.  
  1110.             if (( flags & tcp_FlagFIN ) && (s->state != tcp_StateCLOSWT )
  1111.                 && ( s->acknum == intel( tp->seqnum ))) {
  1112.                 s->acknum ++;
  1113.                 s->err_msg = "Connection closed";
  1114.                 s->state = tcp_StateCLOSWT;
  1115.                 tcp_send( s, __LINE__ );
  1116.                 s->state = tcp_StateLASTACK;
  1117.                 s->flags |= tcp_FlagFIN;
  1118.                 s->unhappy = true;
  1119.             }
  1120.  
  1121.             if ( diff > 0 || len > 0 ) {
  1122.                 /* need to update window, but how urgent ??? */
  1123.                 if ( diff > 0 ) {
  1124.                     tcp_send( s, __LINE__ );
  1125.                 } else
  1126.                     tcp_sendsoon( s );
  1127.  
  1128.             }
  1129.             if ( s->state == tcp_StateESTCL )
  1130.                 tcp_close( s );
  1131.         return( 1 );
  1132.         break;    /* dummy for compiler */
  1133.  
  1134.     case tcp_StateFINWT1:
  1135.         /* They have not necessarily read all the data yet, we must
  1136.            still supply it as requested */
  1137.  
  1138.         ldiff = intel( tp->acknum ) - s->seqnum;
  1139.         diff = (int) ldiff;
  1140.         if ( ldiff >= 0 && diff <= s->datalen ) {
  1141.         s->datalen -= diff;
  1142.                 s->unacked -= diff;
  1143.                 if (s->datalen < 0) s->datalen = 0;
  1144.                 if ( s->queuelen ) {
  1145.                     s->queue += diff;
  1146.                     s->queuelen -= diff;
  1147.                 } else
  1148.                     movmem(s->data + diff, s->data, s->datalen );
  1149.         s->seqnum += ldiff;
  1150.                 if (ldiff == 0 || s->unacked < 0) s->unacked = 0;
  1151.  
  1152.         }
  1153.  
  1154.         /* they may still be transmitting data, we must read it */
  1155.  
  1156.         tcp_ProcessData(s, tp, len);
  1157.  
  1158.         /* check if other tcp has acked all sent data and is ready
  1159.            to change states */
  1160.  
  1161.             if ( flags & (tcp_FlagFIN|tcp_FlagACK) == tcp_FlagFIN|tcp_FlagACK) {
  1162.         /* trying to do similtaneous close */
  1163.         if (( intel( tp->acknum ) >= s->seqnum + 1 ) &&
  1164.             ( intel( tp->seqnum) == s->acknum )) {
  1165.             s->seqnum++;
  1166.             s->acknum++;
  1167.             s->flags = tcp_FlagACK;
  1168.                     tcp_send( s, __LINE__ );
  1169.                     s->unhappy = false;
  1170.                     s->timeout = set_timeout( 2 );
  1171.                     s->state = tcp_StateCLOSED;
  1172.         }
  1173.         } else if ( flags & tcp_FlagACK ) {
  1174.         /* other side is legitimately acking our fin */
  1175.         if (( intel( tp->acknum ) == s->seqnum + 1 ) &&
  1176.             ( intel( tp->seqnum ) == s->acknum ) &&
  1177.             (  s->datalen == 0 )) {
  1178.                         s->seqnum++;
  1179.                         s->acknum++;
  1180.                         s->state = tcp_StateFINWT2;
  1181.                         s->timeout = set_timeout( 3 );
  1182.                         s->unhappy = false; /* we don't send anything */
  1183.         }
  1184.         }
  1185.         break;
  1186.  
  1187.     case tcp_StateFINWT2:
  1188.         if ((flags & (tcp_FlagACK | tcp_FlagFIN)) ==
  1189.           tcp_FlagACK | tcp_FlagFIN) {
  1190.         if (( intel( tp->acknum ) == s->seqnum ) &&
  1191.             ( intel( tp->seqnum ) == s->acknum )) {
  1192.             s->acknum++;
  1193.             s->flags = tcp_FlagACK;
  1194.                     tcp_send( s, __LINE__ );
  1195.             s->unhappy = false;    /* we don't send anything */
  1196.             s->timeout = set_timeout( 2 );
  1197.                     s->state = tcp_StateCLOSED;
  1198.             return( 1 );
  1199.         }
  1200.         }
  1201.         break;
  1202.  
  1203.     case tcp_StateCLOSING:
  1204.         if ((flags & (tcp_FlagACK | tcp_FlagFIN)) == tcp_FlagACK ) {
  1205.         if (( tp->acknum == intel(s->seqnum) ) &&
  1206.             ( tp->seqnum == intel(s->acknum))) {
  1207.             s->state = tcp_StateTIMEWT;
  1208.             s->timeout = set_timeout( tcp_TIMEOUT );
  1209.             s->unhappy = false;
  1210.         }
  1211.         }
  1212.         break;
  1213.  
  1214.     case tcp_StateLASTACK:
  1215.         if ( flags & tcp_FlagFIN ) {
  1216.         /* they lost our two packets, back up */
  1217.         s->flags = tcp_FlagACK | tcp_FlagFIN;
  1218.                 tcp_send( s, __LINE__ );
  1219.                 s->unhappy = TRUE;  /* FALSE; */
  1220.         return( 1 );
  1221.         } else {
  1222.         if (( intel( tp->acknum ) == (s->seqnum + 1 )) &&
  1223.             ( intel( tp->seqnum ) == s->acknum )) {
  1224.             s->state = tcp_StateCLOSED;     /* no 2msl necessary */
  1225.             s->unhappy = false;             /* we're done */
  1226.             return( 1 );
  1227.             }
  1228.         }
  1229.         break;
  1230.  
  1231.     case tcp_StateTIMEWT:
  1232.             if ( flags & (tcp_FlagACK | tcp_FlagFIN) == tcp_FlagACK | tcp_FlagFIN) {
  1233.                 /* he needs an ack */
  1234.                 s->flags = tcp_FlagACK;
  1235.                 tcp_send( s, __LINE__ );
  1236.                 s->unhappy = false;
  1237.                 s->state = tcp_StateCLOSED;     /* support 2 msl in rst code */
  1238.             }
  1239.             break;
  1240.     }
  1241.     if (s->unhappy) tcp_sendsoon(s);
  1242. }
  1243.  
  1244. /*
  1245.  * Process the data in an incoming packet.
  1246.  * Called from all states where incoming data can be received: established,
  1247.  * fin-wait-1, fin-wait-2
  1248.  */
  1249. static tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len)
  1250. {
  1251.     long ldiff;
  1252.     int diff, x;
  1253.     word flags;
  1254.     byte *dp;
  1255.  
  1256.     word *options, numoptions, opt_temp;
  1257.  
  1258.     s->window = intel16( tp->window );
  1259.  
  1260.     flags = intel16( tp->flags );
  1261.     ldiff = s->acknum - intel( tp->seqnum );
  1262.  
  1263.     if ( flags & tcp_FlagSYN ) ldiff--;  /* back up to 0 */
  1264.     diff = (int) ldiff;
  1265.  
  1266.     /* find the data portion */
  1267.     x = tcp_GetDataOffset(tp) << 2;    /* quadword to byte format */
  1268.     dp = (byte *)tp + x;
  1269.  
  1270.     /* process those options */
  1271.     if ( numoptions = x - sizeof( tcp_Header )) {
  1272.         options = (byte *)(tp) + sizeof( tcp_Header);
  1273.     while ( numoptions-- > 0 ) {
  1274.         switch ( *options++ ) {
  1275.         case  0 : numoptions = 0;    /* end of options */
  1276.               break;
  1277.         case  1 : break;        /* nop */
  1278.  
  1279.               /* we are very liberal on MSS stuff */
  1280.         case  2 : if (*options == 2) {
  1281.                   opt_temp = intel16( *(word*)(&options[1]));
  1282.                   if (opt_temp < s->mss )
  1283.                   s->mss = opt_temp;
  1284.               }
  1285.               numoptions -= 2 + *options;
  1286.               options += *options;
  1287.               break;
  1288.         }
  1289.     }
  1290.     }
  1291.     /* done option processing */
  1292.  
  1293.     len -= x;        /* remove the header length */
  1294.     if ( ldiff >= 0 ) {  /* skip already received bytes */
  1295.     dp += diff;
  1296.     len -= diff;
  1297.  
  1298.     if (s->dataHandler) {
  1299.         s->acknum += s->dataHandler(s, dp, len);
  1300.     } else {
  1301.         /* no handler, just dump to buffer, should be indexed, handles goofs */
  1302.         /* limit receive size to our window */
  1303.         if ( s->rdatalen >= 0 ) {
  1304.                 if ( len > ( x = tcp_MaxBufSize - s->rdatalen )) {
  1305.             len = x;
  1306.                 }
  1307.         if ( len > 0 ) {
  1308.             s->acknum += len;    /* our new ack begins at end of data */
  1309.                     movmem(dp, s->rdata + s->rdatalen, len );
  1310.             s->rdatalen += len;
  1311. /*
  1312.                     s->karn_count = 3;
  1313. */
  1314.         }
  1315.         }
  1316.         }
  1317.         s->unhappy = (s->datalen) ? true : false;
  1318.         if (ldiff == 0 && s->unacked && chk_timeout( s->rtt_lasttran )) {
  1319. #ifdef DEBUG
  1320.             if(debug_on >1) printf("data process timeout so set unacked back to 0 from %u\n",s->unacked);
  1321. #endif DEBUG
  1322.             s->unacked = 0;
  1323.         }
  1324.     } else {
  1325.         tcp_sendsoon( s );
  1326.     }
  1327.  
  1328.     s->timeout = set_timeout( tcp_TIMEOUT );
  1329.     return;
  1330. }
  1331.  
  1332. /*
  1333.  * Format and send an outgoing segment
  1334.  */
  1335. static tcp_send(tcp_Socket *s, int line)
  1336. {
  1337.     tcp_PseudoHeader ph;
  1338.     struct _pkt {
  1339.     in_Header in;
  1340.     tcp_Header tcp;
  1341.     word maxsegopt[2];
  1342.     } *pkt;
  1343.     byte *dp;
  1344.     in_Header *inp;
  1345.     tcp_Header *tcpp;
  1346.     int senddatalen, sendtotlen, sendpktlen, startdata, sendtotdata;
  1347.  
  1348.     int ippkt;         /* 1..s->cwindow */
  1349.  
  1350.     s->recent = 0;
  1351.     pkt = (struct _pkt *)_eth_formatpacket(&s->hisethaddr[0], /*0x800*/ 8);
  1352.     dp = &pkt->maxsegopt;  /* dp constant for multi-packet sends */
  1353.     inp = &pkt->in;
  1354.     tcpp = &pkt->tcp;
  1355.  
  1356.  
  1357.     /* this is our total possible send size */
  1358.     if ( s->karn_count != 2 ) {
  1359.         sendtotdata = min( s->datalen - s->unacked, s->window );
  1360.         startdata = s->unacked;
  1361.     } else {
  1362.         sendtotdata = (s->datalen >= s->window)? s->window : s->datalen;
  1363.         startdata = 0;
  1364.     }
  1365. /*
  1366.     if (sendtotdata < 0) sendtotdata = 0;
  1367. */
  1368.     sendtotlen = 0;    /* running count of what we've sent */
  1369.  
  1370.     /* step through our packets */
  1371.     for ( ippkt = 1; ippkt <= s->cwindow; ++ippkt ) {
  1372.         /* adjust size for each packet */
  1373.         senddatalen = min( sendtotdata, s->mss );
  1374.  
  1375.     /*
  1376.         sendpktlen = senddatalen + sizeof( tcp_Header ) + sizeof( in_Header );
  1377.         inp->length = intel16( sendpktlen );
  1378.     */
  1379.         /* tcp header */
  1380.         tcpp->srcPort = intel16( s->myport );
  1381.         tcpp->dstPort = intel16( s->hisport );
  1382.         tcpp->seqnum = intel( s->seqnum + startdata ); /* unacked - no longer sendtotlen */
  1383.         tcpp->acknum = intel( s->acknum );
  1384.  
  1385.         tcpp->window = intel16( s->rmaxdatalen - s->rdatalen );
  1386.         tcpp->flags = intel16( s->flags | 0x5000 );
  1387.         tcpp->checksum = 0;
  1388.         tcpp->urgentPointer = 0;
  1389.  
  1390.         /* do options if this is our first packet */
  1391.         if ((s->flags & (tcp_FlagSYN | tcp_FlagACK)) == tcp_FlagSYN) {
  1392.             sendpktlen = sizeof( tcp_Header ) + sizeof( in_Header ) + 4;
  1393.             tcpp->flags = intel16( intel16( tcpp->flags) + 0x1000 );
  1394.             pkt->maxsegopt[0] = 0x0402;
  1395.             pkt->maxsegopt[1] = intel16( s->mss );
  1396.             dp += 4;
  1397.         } else {
  1398.             /* handle packets with data */
  1399.             if (senddatalen > 0) {
  1400.                 sendpktlen = senddatalen + sizeof( tcp_Header ) + sizeof( in_Header );
  1401.  
  1402.                 /* get data from appropriate place */
  1403.                 if (s->queuelen) movmem(s->queue + startdata, dp, senddatalen );
  1404.                 else movmem(s->data + startdata, dp, senddatalen);
  1405. /*                dp[ senddatalen ] = 0; */
  1406.             } else {
  1407.             /* handle no-data, not-first-SYN packets */
  1408.                 sendpktlen = sizeof( tcp_Header ) + sizeof( in_Header );
  1409.             }
  1410.         }
  1411.  
  1412.         /* internet header */
  1413.         inp->ver = 4;
  1414.         inp->hdrlen = 5;
  1415.         inp->tos = 0;
  1416.         inp->identification = intel16( ++ip_id );   /* was post inc */
  1417.         inp->frag = 0;
  1418.         inp->ttl = 254;
  1419.         inp->proto = TCP_PROTO;
  1420.         inp->checksum = 0;
  1421.         inp->source = intel( my_ip_addr );
  1422.         inp->destination = intel( s->hisaddr );
  1423.         inp->length = intel16( sendpktlen );
  1424.  
  1425.         inp->checksum = ~checksum( inp, sizeof(in_Header));
  1426.  
  1427.         /* compute tcp checksum */
  1428.         ph.src = inp->source;   /* already INTELled */
  1429.         ph.dst = inp->destination;
  1430.         ph.mbz = 0;
  1431.         ph.protocol = 6;
  1432.         ph.length = intel16( sendpktlen - sizeof(in_Header));
  1433. /*
  1434.         ph.checksum = checksum(&pkt->tcp, (sendpktlen - sizeof(in_Header) +1) & 0xfffe);
  1435. */
  1436.         ph.checksum = checksum(&pkt->tcp, sendpktlen - sizeof(in_Header));
  1437.  
  1438.         tcpp->checksum = ~checksum(&ph, sizeof(ph));
  1439.  
  1440.         if (_dbugxmit) (*_dbugxmit)(s,inp,tcpp);
  1441.         if (debug_on > 1) {
  1442. #ifndef WINDOWS
  1443.             mono[0]++;
  1444.             colour[0]++;
  1445.             mono[2] = colour[2] = (s->flags & tcp_FlagSYN) ? 'S' : ' ';
  1446.             mono[4] = colour[4] = (s->flags & tcp_FlagACK) ? 'A' : ' ';
  1447.             mono[6] = colour[6] = (s->flags & tcp_FlagFIN) ? 'F' : ' ';
  1448.             mono[8] = colour[8] = (s->flags & tcp_FlagRST) ? 'R' : ' ';
  1449. #endif
  1450.         }
  1451.         if ( _eth_send( intel16( inp->length ))) { /* encounterred error */
  1452.             tcp_sendsoon( s );
  1453.             return;
  1454.         }
  1455.  
  1456.         /* do next ip pkt */
  1457.         sendtotlen += senddatalen;
  1458.         startdata += senddatalen;
  1459.         sendtotdata -= senddatalen;
  1460.         if (sendtotdata <= 0 ) break;
  1461.     }
  1462.     s->unacked = startdata;
  1463. #ifdef DEBUG
  1464. if (debug_on) printf(" Sent %u/%u bytes in %u/%u packets  with (%u) unacked  SYN %lu  line %u\n",
  1465.         sendtotlen, s->window, ippkt, s->cwindow, s->unacked, s->seqnum, line);
  1466. #endif DEBUG
  1467.     s->vj_last = 0;
  1468.     if ( s->karn_count == 2 ) {
  1469.         if (s->rto) s->rto = (s->rto * 3) / 2;
  1470.         else s->rto = 4;
  1471.     } else {
  1472.         /* vj_last nonzero if we expect an immediate response */
  1473.         if (s->unhappy || s->datalen)
  1474.             s->vj_last = set_ttimeout( 0 );
  1475.     s->karn_count = 0;
  1476.     }
  1477.     s->rtt_time = set_ttimeout( s->rto + 2 );
  1478.     if (sendtotlen > 0 ) s->rtt_lasttran =  s->rtt_time + s->rto;
  1479. }
  1480. /*
  1481.  * Format and send a reset tcp packet
  1482.  */
  1483. tcp_rst( in_Header *his_ip, tcp_Header *oldtcpp)
  1484. {
  1485.     tcp_PseudoHeader ph;
  1486.     struct _pkt {
  1487.         in_Header in;
  1488.         tcp_Header tcp;
  1489.     word maxsegopt[2];
  1490.     } *pkt, *his_pkt;
  1491.  
  1492.     static longword nextrst = 0L;
  1493.     byte *dp;
  1494.     word oldflags;
  1495.     in_Header *inp;
  1496.     tcp_Header *tcpp;
  1497.     eth_Header *eth;
  1498.     int sendtotlen;    /* length of packet */
  1499.     longword templong;
  1500.  
  1501.     /* see RFC 793 page 65 for details */
  1502.  
  1503.     if ( !chk_timeout( nextrst )) return;
  1504.     nextrst = set_ttimeout( 1 );
  1505.  
  1506.     oldflags = intel16( oldtcpp->flags );
  1507.     if (oldflags & tcp_FlagRST ) return( 0 );
  1508.     if ( (oldflags & (tcp_FlagACK | tcp_FlagFIN)) == (tcp_FlagACK | tcp_FlagFIN) ){
  1509.         templong = oldtcpp->seqnum;
  1510.         oldtcpp->seqnum = oldtcpp->acknum;
  1511.         oldtcpp->acknum = templong;
  1512.         oldflags = tcp_FlagACK;
  1513.     } else if ((oldflags & (tcp_FlagSYN | tcp_FlagACK)) ==  tcp_FlagSYN ) {
  1514.         oldtcpp->acknum = intel( intel( oldtcpp->seqnum ) + 1 );
  1515.         oldtcpp->seqnum = 0;
  1516.         oldflags = tcp_FlagACK | tcp_FlagRST;
  1517.     } else if ( oldflags & tcp_FlagACK ) {
  1518.         oldtcpp->seqnum = oldtcpp->acknum;
  1519.         oldtcpp->acknum = 0;
  1520.     } else {
  1521.         oldtcpp->acknum = intel( intel(oldtcpp->seqnum) + 1);
  1522.         oldtcpp->seqnum = 0;
  1523.     }
  1524.     if ( oldflags & ( tcp_FlagFIN | tcp_FlagSYN ) == 0 )
  1525.         oldflags ^= tcp_FlagACK | tcp_FlagRST;
  1526.  
  1527.     his_pkt  = (struct _pkt*)( his_ip );
  1528.  
  1529.     /* convoluted mechanism - reads his ethernet address or garbage */
  1530.     eth = _eth_hardware( his_ip );
  1531.  
  1532.     pkt = (struct _pkt *)_eth_formatpacket( eth, 8);
  1533.     dp = &pkt->maxsegopt;
  1534.     inp = &pkt->in;
  1535.     tcpp = &pkt->tcp;
  1536.  
  1537.     sendtotlen = sizeof( tcp_Header ) + sizeof( in_Header );
  1538.     inp->length = intel16( sendtotlen );
  1539.  
  1540.     /* tcp header */
  1541.     tcpp->srcPort = oldtcpp->dstPort;
  1542.     tcpp->dstPort = oldtcpp->srcPort;
  1543.     tcpp->seqnum = oldtcpp->seqnum;
  1544.     tcpp->acknum = oldtcpp->acknum;
  1545.     tcpp->window = 0;
  1546.     tcpp->flags = intel16( oldflags );
  1547.     tcpp->checksum = 0;
  1548.     tcpp->urgentPointer = 0;
  1549.  
  1550.     /* internet header */
  1551.     inp->ver = 4;
  1552.     inp->hdrlen = 5;
  1553.     inp->tos = 0;
  1554.     inp->identification = intel16( ++ip_id );
  1555.     inp->frag = 0;
  1556.     inp->ttl = 254;
  1557.     inp->proto = TCP_PROTO;
  1558.     inp->checksum = 0;
  1559.     inp->source = his_ip->destination;
  1560.     inp->destination = his_ip->source;
  1561.  
  1562.     inp->checksum = ~checksum( inp, sizeof(in_Header))/* 0*/; /* Watstar */
  1563.  
  1564.     /* compute tcp checksum */
  1565.     ph.src = inp->source;    /* already INTELled */
  1566.     ph.dst = inp->destination;
  1567.     ph.mbz = 0;
  1568.     ph.protocol = 6;
  1569.     ph.length = intel16( sendtotlen - sizeof(in_Header));
  1570.  
  1571.     ph.checksum = checksum(&pkt->tcp, (sendtotlen - sizeof(in_Header) +1) & 0xfffe);
  1572.     /* intel16(ph.length));*/ /* 0; *//* watstar */
  1573.     tcpp->checksum =  ~checksum(&ph, sizeof(ph));
  1574.  
  1575.     if (_dbugxmit) (*_dbugxmit)(NULL,inp,tcpp);
  1576.     _eth_send( intel16( inp->length ));
  1577. }
  1578.  
  1579.  
  1580.  
  1581.  
  1582. /**********************************************************************
  1583.  * socket functions
  1584.  **********************************************************************/
  1585.  
  1586. /* socket based stuff */
  1587.  
  1588. /*
  1589.  * sock_read - read a socket with maximum n bytes
  1590.  *         - busywaits until buffer is full but calls s->usr_yield
  1591.  *         - returns count also when connection gets closed
  1592.  */
  1593. sock_read(sock_type *s, byte *dp, int len )
  1594. {
  1595.     int templen, count;
  1596.     count = 0;
  1597.     do {
  1598.     if ( s->udp.ip_type == UDP_PROTO )
  1599.             templen = udp_read( s, dp, len );
  1600.     else
  1601.         templen = tcp_read( s, dp, len);
  1602.         if (s->tcp.usr_yield) (s->tcp.usr_yield)();
  1603.         if (templen < 1 ) {
  1604.             if (!tcp_tick( s )) return( count );
  1605.         } else {
  1606.             count += templen;
  1607.             dp += templen;
  1608.             len -= templen;
  1609.         }
  1610.     } while ( len );
  1611.     return( count );
  1612. }
  1613. /*
  1614.  * sock_fead - read a socket with maximum n bytes
  1615.  *         - does not busywait until buffer is full
  1616.  */
  1617. sock_fastread(sock_type *s, byte *dp, int len )
  1618. {
  1619.     if ( s->udp.ip_type == UDP_PROTO )
  1620.     len = udp_read( s, dp, len );
  1621.     else
  1622.     len = tcp_read( s, dp, len);
  1623.     return( len );
  1624. }
  1625.  
  1626.  
  1627. /*
  1628.  * sock_write - writes data and returns length written
  1629.  *          - does not perform flush
  1630.  *          - repeatedly calls s->usr_yield
  1631.  */
  1632.  
  1633. sock_write(sock_type *s, byte *dp, int len)
  1634. {
  1635.     int offset, oldlen, oldmode, proto;
  1636.  
  1637.     oldlen = len;
  1638.     offset = 0;
  1639.  
  1640.     proto = (s->udp.ip_type == TCP_PROTO);
  1641.     if ( proto ) oldmode = s->tcp.flags & tcp_FlagPUSH;
  1642.     while ( len  > 0) {
  1643.         if (proto) {
  1644.             s->tcp.flags |= oldmode;
  1645.             offset += tcp_Write( s, &dp[ offset ], len);
  1646.         } else
  1647.         offset += udp_Write( s, &dp[ offset ], len );
  1648.     len = oldlen - offset;
  1649.     if (s->udp.usr_yield)(s->udp.usr_yield)();
  1650.     if (!tcp_tick(s)) return( 0 );
  1651.     }
  1652.     return( oldlen );
  1653. }
  1654.  
  1655.  
  1656.  
  1657. sock_fastwrite(sock_type *s, byte *dp, int len)
  1658. {
  1659.     return( ( s->udp.ip_type == UDP_PROTO ) ?
  1660.     udp_Write( s, dp, len ) :
  1661.     tcp_Write( s, dp, len) );
  1662. }
  1663.  
  1664. void sock_enqueue(sock_type *s, byte *dp, int len)
  1665. {
  1666.     int written;
  1667.     if ( s->udp.ip_type == UDP_PROTO ) {
  1668.         do {
  1669.             written = udp_Write( s, dp, len );
  1670.             dp += written;
  1671.         } while (len -= written > 0);
  1672.     } else {
  1673.         s->tcp.queue = dp;
  1674.         s->tcp.queuelen = len;
  1675.         s->tcp.datalen = len;
  1676.         tcp_send( s, __LINE__ );  /* start sending it */
  1677.     }
  1678. }
  1679.  
  1680.  
  1681. sock_flush( sock_type *s )
  1682. {
  1683.     if ( s->tcp.ip_type == TCP_PROTO )
  1684.     tcp_Flush( s );
  1685. }
  1686.  
  1687. /*
  1688.  * sock_flushnext - cause next transmission to have a flush
  1689.  */
  1690. sock_flushnext( sock_type *s)
  1691. {
  1692.     if (s->tcp.ip_type == TCP_PROTO )
  1693.     s->tcp.flags |= tcp_FlagPUSH;
  1694. }
  1695. /*
  1696.  * sock_putc - put a character
  1697.  *         - no expansion but flushes on '\n'
  1698.  *         - returns character
  1699.  */
  1700. byte sock_putc( sock_type *s, byte c )
  1701. {
  1702.     if (( c == '\n') || ( c == '\r'))
  1703.     sock_flushnext( s );
  1704.     sock_write( s, &c, 1 );
  1705.     return( c );
  1706. }
  1707.  
  1708. word sock_getc( sock_type *s )
  1709. {
  1710.     char ch;
  1711.     sock_read( s, &ch, 1 );
  1712.     return( ch );
  1713. }
  1714.  
  1715. /*
  1716.  * sock_puts - does not append carriage return in binary mode
  1717.  *         - returns length
  1718.  */
  1719. sock_puts( sock_type *s, byte *dp )
  1720. {
  1721.     int len;
  1722.     len = strlen( dp );
  1723.     sock_flushnext( s );
  1724.     sock_write( s, dp, len );
  1725.     if (s->tcp.sock_mode & TCP_MODE_ASCII )
  1726.         sock_write( s, "\r\n", 2 );
  1727.     return( len );
  1728. }
  1729.  
  1730. /*
  1731.  * sock_update - update the socket window size to the other guy
  1732.  */
  1733. static sock_update( tcp_Socket *s )
  1734. {
  1735.     if (s->ip_type == TCP_PROTO) {
  1736.     if ( s->rdatalen < ( 3 * s->rmaxdatalen) / 4 )
  1737.             tcp_send( s, __LINE__ );              /* update the window */
  1738.     else
  1739.         tcp_sendsoon( s );
  1740.     }
  1741. }
  1742. /*
  1743.  * sock_gets - read a string from any socket
  1744.  *         - return length of returned string
  1745.  *         - removes end of line terminator
  1746.  */
  1747. word sock_gets( sock_type *s, byte *dp, int n )
  1748. {
  1749.     int len, templen;
  1750.     char *src_p, *temp, *temp2;
  1751.     char *endn, *endr;        /* used since we do not list strpbrk */
  1752.     word *np;
  1753.     
  1754.     char *src, *dest, *tempp;
  1755.  
  1756.     if ( n > tcp_MaxBufSize ) n = tcp_MaxBufSize;
  1757.  
  1758.     if ( s->udp.ip_type == UDP_PROTO ) {
  1759.     src_p = s->udp.rdata;
  1760.     np = &s->udp.rdatalen;
  1761.     } else {
  1762.     src_p = s->tcp.rdata;
  1763.     np = &s->tcp.rdatalen;
  1764.     }
  1765.  
  1766.     src_p[ *np ] = 0;         /* terminate string */
  1767.     strncpy( dp, src_p, n );    /* copy everything */
  1768.     dp[ n-1 ] = 0;        /* terminate */
  1769.  
  1770.     if (temp = strchr( dp, '\n')) *temp = 0;
  1771.     if (temp2= strchr( dp, '\r')) *temp2= 0;
  1772.     len = strlen( dp );
  1773.  
  1774.     /* skip if there were no crs or lfs ??? */
  1775.     if (!temp2 && !temp && ( strlen( dp ) < n - 1) ) {
  1776.  
  1777.         if ( s->udp.ip_type == TCP_PROTO &&
  1778.              s->tcp.state != tcp_StateESTAB &&
  1779.              s->tcp.state != tcp_StateESTCL &&
  1780.              s->tcp.state != tcp_StateCLOSWT )
  1781.             /* take what we can get from this connection */;
  1782.         else {
  1783.             *dp = 0;
  1784.             return( 0 );
  1785.         }
  1786.     }
  1787.  
  1788.     /* skip over \n and \r but stop on end */
  1789. #ifndef OLD
  1790.     if ( temp ) templen = FP_OFF( temp ) - FP_OFF( dp );
  1791.     else if ( temp2 ) templen = FP_OFF( temp2 ) - FP_OFF( dp );
  1792.     else templen = len + 1;
  1793.  
  1794.     if (templen) {
  1795.         ++templen;
  1796.         movmem( &src_p[ templen ], src_p, *np -= templen);
  1797.     } else
  1798.         * np = 0;
  1799. #else
  1800.     temp = &src_p[ len + 1 ];
  1801.     while ( *temp && (    ( *temp == '\n' ) || (*temp == '\r')))
  1802.     temp++;
  1803.  
  1804.     if (*temp)
  1805.     movmem( temp, src_p, *np = strlen( temp ));
  1806.     else
  1807.     *np = 0;
  1808. #endif OLD
  1809.  
  1810.     sock_update( s );    /* new window */
  1811.     return( len );
  1812. }
  1813.  
  1814.  
  1815. /*
  1816.  * sock_dataready - returns number of bytes waiting to be ready
  1817.  *          - if in ASCII mode, return 0 until a line is present
  1818.  *            or the buffer is full
  1819.  */
  1820. word sock_dataready( sock_type *s )
  1821. {
  1822.     int len;
  1823.     char *p;
  1824.  
  1825.     if ((len = s->tcp.rdatalen) == -1) return( -1 );
  1826.  
  1827.     if (s->tcp.sock_mode & TCP_MODE_ASCII) {
  1828.         if ( len == tcp_MaxBufSize )
  1829.             return( tcp_MaxBufSize );
  1830.         /* check for terminating \n \r */
  1831.         p = s->tcp.rdata;
  1832.         if ( strchr( p , '\n') || strchr( p, '\r'))
  1833.             return( len );
  1834.         return( 0 );
  1835.     } else
  1836.         return( len );
  1837. }
  1838.  
  1839. sock_established( sock_type *s )
  1840. {
  1841.     switch ( s->tcp.ip_type ) {
  1842.     case UDP_PROTO :
  1843.         return( 1 );
  1844.     case TCP_PROTO :
  1845.                 return( s->tcp.state == tcp_StateESTAB ||
  1846.                         s->tcp.state == tcp_StateESTCL ||
  1847.                         s->tcp.state == tcp_StateCLOSWT );
  1848.     default :
  1849.         return( 0 );
  1850.     }
  1851. }
  1852.  
  1853. sock_close( s )
  1854. sock_type *s;
  1855. {
  1856.     switch (s->udp.ip_type) {
  1857.     case UDP_PROTO :
  1858.         udp_close( s );
  1859.         break;
  1860.     case TCP_PROTO :
  1861.         tcp_close( s );
  1862.         tcp_tick( s );
  1863.         break;
  1864.     }
  1865. }
  1866.  
  1867.  
  1868. /*
  1869.  * _ip_delay0 called by macro sock_wait_established()
  1870.  * _ip_delay1 called by macro sock_wait_intput()
  1871.  * _ip_delay2 called by macro sock_wait_closed();
  1872.  *
  1873.  */
  1874.  
  1875. _ip_delay0( s, timeoutseconds, fn, statusptr )
  1876. sock_type *s;
  1877. int timeoutseconds;
  1878. procref fn;
  1879. int *statusptr;
  1880. {
  1881.     int status;
  1882.     ip_timer_init( s , timeoutseconds );
  1883.     do {
  1884.     if ( s->tcp.ip_type == TCP_PROTO ) {
  1885.         if ( tcp_established( s )) {
  1886.         status = 0;
  1887.         break;
  1888.         }
  1889.     }
  1890.     kbhit();    /* permit ^c */
  1891.     if ( !tcp_tick( s )) {
  1892.          s->tcp.err_msg = "Host refused connection";
  1893.          status = -1;    /* get an early reset */
  1894.          break;
  1895.     }
  1896.     if ( ip_timer_expired( s )) {
  1897.         sock_close( s );
  1898.         status = -1;
  1899.         break;
  1900.     }
  1901.     if ( fn ) if (status = fn(s)) break;
  1902.     if ( s->tcp.usr_yield ) (*s->tcp.usr_yield)();
  1903.     if ( s->tcp.ip_type == UDP_PROTO ) {
  1904.         status = 0;
  1905.         break;
  1906.     }
  1907.     } while ( 1 );
  1908.     if (statusptr) *statusptr = status;
  1909.     return( status );
  1910. }
  1911.  
  1912. _ip_delay1( s, timeoutseconds, fn, statusptr)
  1913. sock_type *s;
  1914. int timeoutseconds;
  1915. procref fn;
  1916. int *statusptr;
  1917. {
  1918.     int status;
  1919.     ip_timer_init( s , timeoutseconds );
  1920.  
  1921.     sock_flush( s );    /* new enhancement */
  1922.  
  1923.     do {
  1924.     if ( sock_dataready( s )) {
  1925.         status = 0;
  1926.         break;
  1927.     }
  1928.     kbhit();    /* permit ^c */
  1929.     if ( !tcp_tick( s )) {
  1930.         status = 1;
  1931.         break;
  1932.     }
  1933.     if ( ip_timer_expired( s )) {
  1934.         sock_close( s );
  1935.         status = -1;
  1936.         break;
  1937.     }
  1938.     if (fn) {
  1939.         if (status = fn(s))
  1940.         break;
  1941.     }
  1942.     if ( s->tcp.usr_yield ) (*s->tcp.usr_yield)();
  1943.     } while ( 1 );
  1944.     if (statusptr) *statusptr = status;
  1945.     return( status );
  1946. }
  1947.  
  1948. _ip_delay2( s, timeoutseconds, fn, statusptr)
  1949. sock_type *s;
  1950. int timeoutseconds;
  1951. procref fn;
  1952. int *statusptr;
  1953. {
  1954.     int status;
  1955.     ip_timer_init( s , timeoutseconds );
  1956.  
  1957.     if (s->tcp.ip_type != TCP_PROTO ) return( 1 );
  1958.  
  1959.     do {
  1960. /*
  1961.     while ( sock_dataready( s ))
  1962.         sock_fastread( s, &status, 1 );
  1963. */
  1964.     kbhit();    /* permit ^c */
  1965.     if ( !tcp_tick( s )) {
  1966.         status = 1;
  1967.         break;
  1968.     }
  1969.     if ( ip_timer_expired( s )) {
  1970.         sock_abort( s );
  1971.         status = -1;
  1972.         break;
  1973.     }
  1974.     if (fn) {
  1975.         if (status = fn(s))
  1976.         break;
  1977.     }
  1978.     if ( s->tcp.usr_yield ) (*s->tcp.usr_yield)();
  1979.  
  1980.     } while ( 1 );
  1981.     if (statusptr) *statusptr = status;
  1982.     return( status );
  1983. }
  1984.  
  1985.  
  1986. char *rip( char *s )
  1987. {
  1988.     char *temp;
  1989.  
  1990.     if (temp = strchr( s, '\n')) *temp = 0;
  1991.     if (temp = strchr( s, '\r')) *temp = 0;
  1992.     return( s );
  1993. }
  1994.  
  1995.