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