home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / PPPBCKP / SRC / SRC20A01.ZIP / WATTSRC.ZIP / PCTCP.C < prev    next >
C/C++ Source or Header  |  1998-10-28  |  72KB  |  2,408 lines

  1. /*
  2. file: PCTCP.C (updated version)
  3.  
  4. This file is an "improved" version of the original version (Wat9609).
  5. */
  6.  
  7. /* To undo a fix simply undefine the define that goes with the fix. */
  8. /* 28/10/1998 */
  9. #define __UDP_PASSIVE_SOCKET_BUG__   /* Dashui Zhou <dszhou@cs.sdu.edu.cn> */
  10. #define __UDP_HANDLER_OPTIMIZATION__ /* Dashui Zhou <dszhou@cs.sdu.edu.cn> */
  11. #define __SPURIOUS_ACK_BUG__         /* Joe <jdhagen@itis.com> */
  12. #define __SIGNED_BUG__               /* Morten Terstrup <MorTer@dk-online.dk> */
  13. #define __UDP_BROADCAST_BUG__        /* CpV <crudesoft@yahoo.com> */
  14.  
  15. /*
  16. This file is available from (28/10/1998)
  17.  
  18.      www.geocities.com/SiliconValley/Lab/9247
  19.  
  20. the Web page of Ken Yap <kenyap@research.canon.com.au>
  21.  
  22. Please do NOT send bug reports to Ken Yap, but instead send them to
  23. Clemens Valens at <crudesoft@yahoo.com>
  24.  
  25. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  26. !!                                                                       !!
  27. !! NOTE:                                                                 !!
  28. !!                                                                       !!
  29. !! It is very well possible that the bugs mentioned and fixed here were  !!
  30. !! found and fixed before by others as well. The names listed are the    !!
  31. !! names of the people I know of. If there is someone not credited,      !!
  32. !! please let me know and I will straighten things out.                  !!
  33. !!                                                                       !!
  34. !! Send WATTCP bugs and fixes to: crudesoft@yahoo.com                    !!
  35. !! Please be clear and please explain.                                   !!
  36. !!                                                                       !!
  37. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  38.  
  39. End of non-WATTCP comments.
  40. */
  41.  
  42.  
  43. /* DEBUG flag may be set for my internal playing */
  44.  
  45. /*
  46. #define DEBUG
  47. */
  48.  
  49. /*
  50.  *  PCTCP - the true worker of Waterloo TCP
  51.  *         - contains all opens, closes, major read/write routines and
  52.  *        basic IP handler for incomming packets
  53.  *      - NOTE: much of the TCP/UDP/IP layering is done at the data structure
  54.  *        level, not in separate routines or tasks
  55.  *
  56.  */
  57.  
  58. #include <copyright.h>
  59. #include <time.h>
  60. #include <stdio.h>
  61. #include <stdarg.h>
  62. #include <stdlib.h>
  63. #include <conio.h>
  64. #include <string.h>
  65. #include <mem.h>
  66. #include <dos.h>
  67. #include <values.h>
  68.  
  69. #include "wattcp.h"
  70. #include "elib.h"
  71.  
  72. static void udp_handler(in_Header *ip);
  73. static udp_write(udp_Socket *s, byte *datap, int len, word offset);
  74. static int udp_read(udp_Socket *s, byte *datap, int maxlen);
  75. static void tcp_Retransmitter(void);
  76.  
  77.  
  78. #define TCP_LOCAL 0x4000
  79.  
  80. /* statics */
  81. //static tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len);
  82. static void tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len, // 94.11.19
  83.                                     tcp_PseudoHeader *ph);
  84.  
  85. static char far *mono = (char far *)0xb0000000L;
  86. static char far *colour = (char far *)0xb8000000L;
  87.  
  88. static initialized = 0;
  89. static void (*system_yield)() = NULL;
  90. extern int multihomes;
  91. extern word _pktipofs;
  92. void (*_dbugxmit)( sock_type *s, in_Header *inp, void *phdr, unsigned line ) = NULL;
  93. void (*_dbugrecv)( sock_type *s, in_Header *inp, void *phdr, unsigned line ) = NULL;
  94. void (*wattcpd)(void) = NULL;
  95.  
  96. char *_hostname = "012345678901234567890123456789012345678901234567890";
  97.  
  98. word _mss = ETH_MSS;
  99.  
  100. char *_wattcp = WATTCP_C;
  101.  
  102. static void tcp_handler(in_Header *ip);
  103. static void udp_handler(in_Header *ip);
  104.  
  105. static void tcp_unthread(tcp_Socket *ds);
  106. static void tcp_abort(tcp_Socket *s);
  107. void tcp_sendsoon(tcp_Socket *s );
  108. static void tcp_send(tcp_Socket *s, int line);
  109. static void tcp_rst( in_Header *his_ip, tcp_Header *oldtcpp);
  110. static udp_close(udp_Socket *ds);
  111.  
  112.  
  113. /*
  114.  * sock_yield - enable user defined yield function
  115.  */
  116. int sock_yield( tcp_Socket *s, void (*fn)( void ) )
  117. {
  118.         if ( s )
  119.     s->usr_yield = fn;
  120.     else
  121.     system_yield = fn;
  122.     return( 0 );
  123. }
  124.  
  125. /*
  126.  * sock_mode - set binary or ascii - affects sock_gets, sock_dataready
  127.  *         - set udp checksums
  128.  */
  129. word sock_mode( sock_type *s, word mode )
  130. {
  131.          return( s->tcp.sock_mode = (s->tcp.sock_mode & 0xfffc) | mode);
  132. }
  133.  
  134. /*
  135.  * ip user level timer stuff
  136.  *   void ip_timer_init( void *s, int delayseconds )
  137.  *   int  ip_timer_expired( void *s )
  138.  *    - 0 if not expired
  139.  */
  140. static unsigned long far *realclock = (unsigned long far *)0x000046cL;
  141. #define MAXTICKS 0x1800b0L
  142.  
  143. void ip_timer_init( sock_type *s , int delayseconds )
  144. {
  145.     if (delayseconds)
  146.     s->tcp.usertimer = set_timeout( delayseconds );
  147.     else
  148.     s->tcp.usertimer = 0;
  149. }
  150.  
  151. int ip_timer_expired( sock_type *s )
  152. {
  153.     if (! s->tcp.usertimer)    /* cannot expire */
  154.     return( 0 );
  155.     return( chk_timeout( s->tcp.usertimer));
  156. }
  157.  
  158. longword MsecClock( void )
  159. {
  160.     return( (*realclock) * 055L);
  161. }
  162.  
  163. static long make_timeout( word timeout )
  164. {
  165.     if ( timeout ) return( set_timeout( timeout ));
  166.     return( 0 );
  167. }
  168.  
  169. #if 0    /* 94.11.27 -- not used? */
  170. /*
  171.  * check_timeout - test agains timeout clock - account for overflow
  172.  */
  173. static int check_timeout( unsigned long timeout )
  174. {
  175.     if (timeout) return( chk_timeout( timeout ));
  176.     return( 0 );
  177. }
  178. #endif
  179.  
  180. /*
  181.  * Local IP address
  182.  */
  183. longword my_ip_addr = 0L;    /* for external references */
  184. longword sin_mask = 0xfffffe00L;
  185. longword sin_gate = 0x0;
  186.  
  187.  
  188. /*
  189.  * IP identification numbers
  190.  */
  191.  
  192. static int ip_id = 0;            /* packet number */
  193. static int next_tcp_port = 1024;    /* auto incremented */
  194. static int next_udp_port = 1024;
  195. static tcp_Socket *tcp_allsocs = NULL;
  196. static udp_Socket *udp_allsocs = NULL;
  197.  
  198. /* Timer definitions */
  199. #define RETRAN_STRAT_TIME  1     /* in ticks - how often do we check retransmitter tables*/
  200. #define tcp_RETRANSMITTIME 3     /* interval at which retransmitter is called */
  201. #define tcp_LONGTIMEOUT 31       /* timeout for opens */
  202. #define tcp_TIMEOUT 13           /* timeout during a connection */
  203.  
  204. word debug_on = 0;
  205.  
  206. /*
  207.  * look for bugs
  208.  */
  209. int tcp_checkfor( sock_type *t )
  210. {
  211.         tcp_Socket *p;
  212.  
  213.     for ( p = tcp_allsocs ; p ; p = p->next )
  214.         if ( p == (tcp_Socket *)t ) return( 1 );
  215.     return( 0 );
  216. }
  217.  
  218. /*
  219.  * Shut down the card and all services
  220.  */
  221. void tcp_shutdown( void )
  222. {
  223.     while (tcp_allsocs)
  224.     tcp_abort( tcp_allsocs );
  225.     _eth_release();
  226.     initialized = 0;
  227. }
  228.  
  229. /*
  230.  * tcp_init - Initialize the tcp implementation
  231.  *        - may be called more than once without hurting
  232.  */
  233. void tcp_init( void )
  234. {
  235.     extern int _arp_last_gateway;
  236.     extern int _last_nameserver;
  237.  
  238.         if (!initialized) {
  239.     /* initialize ethernet interface */
  240.     initialized = 1;
  241.     _eth_init();
  242.  
  243.     /* reset the various tables */
  244.     _arp_last_gateway = 0;    /* reset the gateway table */
  245.     _last_nameserver = 0;    /* reset the nameserver table */
  246.     _last_cookie = 0;    /* eat all remaining crumbs */
  247.     *_hostname = 0;        /* reset the host's name */
  248.  
  249.     _eth_free( 0 );
  250.     next_udp_port = next_tcp_port = 1024 + ((*realclock >> 7 )& 0x1ff);
  251.         }
  252. }
  253.  
  254. /*
  255.  * Checks for bugs when compiling in large model C compiler
  256.  *
  257.  * Borland C uses a 4K stack by default.  In all memory models the
  258.  * stack grows down toward the heap.
  259.  *
  260.  * If you accidentally place tcp_Socket onto the stack (like by making
  261.  * it an automatic variable), then you will have already used up that
  262.  * whole 4K and then some!
  263.  *
  264.  * In large model, this will mess up the data space in a major way
  265.  * because the stack starts at SS:_stklen, or SS:1000, so you will
  266.  * wrap the SP pointer back around to FFFE and start writing over
  267.  * the far heap.  Yuck.
  268.  *
  269.  * In small model it usually doesn't kill your application because
  270.  * you would have to be down to your last 4K of memory and this is
  271.  * not as common.
  272.  *
  273.  * The solutions: declare your sockets as static, or put them on the
  274.  * heap, or bump up your stack size by using the global special variable:
  275.  *
  276.  * unsigned _stklen = 16536;    // set stack to 16 k
  277.  */
  278. static void largecheck( void *s, int size )
  279. {
  280. #ifdef __TURBOC__
  281.     if ( (word)(FP_OFF(s)) > (word)(-size)) {
  282.         outs("ERROR: user stack size error\n");
  283.         exit( 3 );
  284.     }
  285. #endif
  286. }
  287.  
  288. /*
  289.  * findfreeport - return unused local port
  290.  *              - oldport = 0:normal port, 1:special port (513-1023)
  291.  *              - we need not be this picky, but it doesn't hurt
  292.  */
  293. static word findfreeport( word oldport )
  294. {
  295.     word temp;
  296.     tcp_Socket *s;
  297.  
  298.         if (( oldport > 0 ) && (oldport < 0xffff))
  299.         return( oldport );
  300.  
  301.     if ( oldport == 0 ) oldport = 1025;
  302.     else oldport = 513;
  303.  
  304.     for ( temp = oldport ; temp < oldport + 510 ; ++temp ) {
  305.         if (( s = (tcp_Socket*)udp_allsocs) != NULL ) {
  306.             while ( s->next && (s->myport != temp))
  307.                 s = (tcp_Socket*)s->next;
  308.             if ( s->myport == temp ) continue;
  309.                 }
  310.         if ( (s = tcp_allsocs ) != NULL ) {
  311.                         while ( s->next && (s->myport != temp ))
  312.                 s = s->next;
  313.             if ( s->myport == temp ) continue;
  314.         }
  315.         break;
  316.     }
  317.     return( temp );
  318. }
  319.  
  320. /* socket, localport, destaddress */
  321. int udp_open( udp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler )
  322. {
  323.     udp_close( s );
  324.     largecheck( s, sizeof( udp_Socket ));
  325.     memset( s, 0, sizeof( udp_Socket ));
  326.     s->rdata = s->rddata;
  327.     s->maxrdatalen = tcp_MaxBufSize;
  328.     s->ip_type = UDP_PROTO;
  329.  
  330.     lport = findfreeport(lport);
  331.  
  332.     s->myport = lport;
  333.     s->myaddr = my_ip_addr;
  334.  
  335.     /* check for broadcast */
  336.     if ( (long)(ina) == -1 || !ina )
  337.     memset( &s->hisethaddr, 0xff, sizeof( eth_address ));
  338.         else if ( ! _arp_resolve(ina, &s->hisethaddr, 0) )
  339.     return( 0 );
  340.  
  341.     s->hisaddr = ina;
  342.     s->hisport = port;
  343.     s->dataHandler = datahandler;
  344.     s->usr_yield = system_yield;
  345.     s->safetysig = SAFETYUDP;
  346.     s->next = udp_allsocs;
  347.     udp_allsocs = s;
  348.     return( 1 );
  349. }
  350.  
  351. /*
  352.  * Actively open a TCP connection to a particular destination.
  353.  *    - 0 on error
  354.  */
  355. int tcp_open( tcp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler )
  356. {
  357.     largecheck( s, sizeof( tcp_Socket ));   /* stack space warnings */
  358.         tcp_unthread(s);                        /* just in case not totally closed */
  359.  
  360.     memset( s, 0, sizeof( tcp_Socket));
  361.     s->rdata = s->rddata;
  362.     s->maxrdatalen = tcp_MaxBufSize;
  363.     s->ip_type = TCP_PROTO;
  364.     s->mss = _mss;
  365.     s->state = tcp_StateSYNSENT;
  366.     s->timeout = set_timeout( tcp_LONGTIMEOUT );
  367.     s->cwindow = 1;
  368.     s->wwindow = 0;     /* slow start VJ algorithm */
  369.         s->vj_sa = 4;      /* about 250 ms */
  370.     lport = findfreeport( lport );  /* get a nonzero port val */
  371.         s->myaddr = my_ip_addr;
  372.     s->myport = lport;
  373.  
  374.     if ( ina - my_ip_addr <= multihomes ) return( 0 );
  375.     if ( ! _arp_resolve(ina, &s->hisethaddr, 0) )
  376.     return( 0 );
  377.  
  378.         s->hisaddr = ina;
  379.     s->hisport = port;
  380.     s->seqnum = intel( set_timeout( 1 )) & 0xffff0000uL;
  381.     s->datalen = 0;
  382.     s->flags = tcp_FlagSYN;
  383.     s->unhappy = true;
  384.     s->dataHandler = datahandler;
  385.     s->usr_yield = system_yield;
  386.  
  387.     s->safetysig = SAFETYTCP;       /* insert into chain */
  388.     s->next = tcp_allsocs;
  389.         tcp_allsocs = s;
  390.  
  391.         s->rtt_delay = s->rtt_smooth = 18;    /* one second startup */
  392.     tcp_send(s, __LINE__ );
  393.     s->rtt_time = set_timeout( 1 );
  394.     return( 1 );
  395. }
  396.  
  397. /*
  398.  * Passive open: listen for a connection on a particular port
  399.  */
  400. int tcp_listen( tcp_Socket *s, word lport, longword ina, word port, dataHandler_t datahandler, word timeout )
  401. {
  402.     largecheck( s, sizeof( tcp_Socket ));
  403.     tcp_unthread(s);                        /* just in case not totally closed */
  404.     memset( s, 0, sizeof( tcp_Socket));
  405.     s->rdata = s->rddata;
  406.     s->maxrdatalen = tcp_MaxBufSize;
  407.     s->ip_type = TCP_PROTO;
  408.     s->mss = _mss;
  409.         s->cwindow = 1;
  410.     s->wwindow = 0;     /* slow start VJ algorithm */
  411. /*    s->vj_sa = 36;      /* about 250 ms */
  412. /* tcpwinfix -- mdurkin */
  413.     s->vj_sa = 4;      /* about 250 ms */    /* was wrong val 95.05.02 */
  414.  
  415.     s->state = tcp_StateLISTEN;
  416.     if ( !timeout ) s->timeout = 0; /* forever... */
  417.     else s->timeout = set_timeout( timeout );
  418.         lport = findfreeport( lport );  /* get a nonzero port val */
  419.     s->myport = lport;
  420.     s->hisport = port;
  421.     s->hisaddr = ina;
  422.     s->seqnum = intel( (word)(s));
  423.     s->datalen = 0;
  424.     s->flags = 0;
  425.     s->unhappy = false;
  426.     s->dataHandler = datahandler;
  427.     s->usr_yield = system_yield;
  428.  
  429.         s->safetysig = SAFETYTCP;       /* insert into chain */
  430.     s->next = tcp_allsocs;
  431.         tcp_allsocs = s;
  432.  
  433.     return( 1 );
  434. }
  435.  
  436. static udp_close( udp_Socket *ds )
  437. {
  438.         udp_Socket *s, **sp;
  439.  
  440.     sp = &udp_allsocs;
  441.     for (;;) {
  442.         s = *sp;
  443.         if ( s == ds ) {
  444.             *sp = s->next;
  445.             break;
  446.         }
  447.     if ( !s ) break;
  448.     if ( ! s->err_msg ) s->err_msg = "UDP Close called";
  449.     sp = &s->next;
  450.     }
  451.         return( 0 );
  452. }
  453.  
  454. /*
  455.  * Send a FIN on a particular port -- only works if it is open
  456.  *   Must still allow receives
  457.  */
  458. static void tcp_close( tcp_Socket *s )
  459. {
  460.     if ( s->ip_type != TCP_PROTO )
  461.     return;
  462.     if ( s->state == tcp_StateESTAB ||
  463.          s->state == tcp_StateESTCL ||
  464.          s->state == tcp_StateSYNREC ) {
  465.  
  466.        if ( s->datalen ) {     /* must first flush all data */
  467.             s->flags |= tcp_FlagPUSH | tcp_FlagACK;
  468.             if ( s->state < tcp_StateESTCL ) {
  469.                                 s->state = tcp_StateESTCL;
  470.         tcp_sendsoon( s );
  471.                         }
  472.         } else { /* really closing */
  473.             s->flags = tcp_FlagACK | tcp_FlagFIN;
  474.             if (!s->err_msg)
  475.                 s->err_msg = "Connection closed normally";
  476.             s->state = tcp_StateFINWT1;
  477.             s->timeout = set_timeout( 4 ); /* should be a pretty lengthy time */
  478.                         tcp_send( s, __LINE__ );
  479.         }
  480.         s->unhappy = true;
  481.     } else if (s->state == tcp_StateCLOSWT ) {
  482.         /* need to ack the fin and get on with it */
  483.         s->state = tcp_StateLASTACK;
  484.         s->flags |= tcp_FlagFIN;
  485.         tcp_send( s, __LINE__ );
  486.         s->unhappy = true;
  487.     }
  488. }
  489.  
  490. /*
  491.  * Abort a tcp connection
  492.  */
  493. static void tcp_abort( tcp_Socket *s )
  494. {
  495.     if (!s->err_msg) s->err_msg = "TCP_ABORT";
  496.     if ( s->state != tcp_StateLISTEN && s->state != tcp_StateCLOSED ) {
  497.         s->flags = tcp_FlagRST  | tcp_FlagACK ;
  498.                 s->unhappy = true;
  499.         tcp_send(s, __LINE__);
  500.     }
  501.     s->unhappy = false;
  502.     s->datalen = 0;
  503.     s->ip_type = 0;
  504.     s->state = tcp_StateCLOSED;
  505. /*    if (s->dataHandler) s->dataHandler(s, 0, -1); */
  506.     tcp_unthread(s);
  507. }
  508.  
  509. void sock_abort( sock_type *s )
  510. {
  511.         if ( s->tcp.ip_type == TCP_PROTO )
  512.     tcp_abort( (tcp_Socket *)s );
  513.     else
  514.         udp_close( (udp_Socket *)s );
  515. }
  516.  
  517. /*
  518.  * tcp_sendsoon - schedule a transmission pretty soon
  519.  *        - this one has an imperfection at midnight, but it
  520.  *          is not significant to the connection performance
  521.  */
  522. void tcp_sendsoon( tcp_Socket *s )
  523. {
  524.     longword temp;
  525.     if (s->ip_type == TCP_PROTO ) {
  526.     temp = set_ttimeout( 1 );
  527.         if ( temp == s->rtt_time && s->rto < 2 && s->recent == 0 ) {
  528.             s->karn_count = 0;
  529.                         tcp_send( s, __LINE__ );
  530.             s->recent = 1;
  531.                         return;
  532.         }
  533.         if ((s->unhappy || s->datalen > 0 || s->karn_count == 1)
  534.           && (s->rtt_time < temp ))
  535.             return;
  536.  
  537.         s->rtt_time = set_ttimeout( 1 + (s->rto >> 4) );
  538.     s->karn_count = 1;
  539.     }
  540. }
  541.  
  542. /*
  543.  * Retransmitter - called periodically to perform tcp retransmissions
  544.  */
  545. static longword retran_strat = 0L; /* timeout retran strategy */
  546.  
  547. static void tcp_Retransmitter( void )
  548. {
  549.         tcp_Socket *s;
  550.  
  551.         /* only do this once per RETRAN_STRAT_TIME milliseconds */
  552.     if ( !chk_timeout( retran_strat ))
  553.     return;
  554.     retran_strat = set_ttimeout( RETRAN_STRAT_TIME );
  555.  
  556.     for ( s = tcp_allsocs; s; s = s->next ) {
  557.         if ( s->datalen > 0 || s->unhappy || s->karn_count == 1 ) {
  558.             /* retransmission strategy */
  559.         if ( chk_timeout( s->rtt_time)) {
  560.  
  561. #ifdef DEBUG
  562.     if(debug_on >1) printf("regular retran TO set unacked back to 0 from %u\n", s->unacked);
  563. #endif DEBUG
  564.                 /* strategy handles closed windows   J.D. + E.E. */
  565.                if (s->window == 0 && s->karn_count == 2)
  566.                   s->window = 1;
  567.  
  568.                 if ( s->karn_count == 0 ) {
  569.                                         /* if really did timeout */
  570.  
  571.  
  572.                     s->karn_count = 2;
  573.  
  574.                     s->unacked = 0;
  575.                     /* use the backed off rto - implied, no code necessary */
  576.                     /* reduce the transmit window */
  577.                     s->cwindow =  ((s->cwindow + 1) * 3) >> 2;
  578.                                         if ( s->cwindow == 0 ) s->cwindow = 1;
  579.                     s->wwindow = 0;
  580.                 }
  581.                 if (s->datalen)
  582.                     s->flags |= tcp_FlagPUSH | tcp_FlagACK;
  583.                 tcp_send(s, __LINE__);
  584.         }
  585.     }
  586.         /* handle inactive tcp timeouts */
  587.         if ( sock_inactive && s->inactive_to ) {
  588.             if ( chk_timeout( s->inactive_to)) {
  589.                                 /* this baby has timed out */
  590.                 s->err_msg = "Connection timed out - no activity";
  591.                                 sock_close( (sock_type *) s );
  592.             }
  593.         }
  594.         if ( s->timeout && chk_timeout( s->timeout)) {
  595.         if ( s->state == tcp_StateTIMEWT ) {
  596.         s->state = tcp_StateCLOSED;
  597.         tcp_unthread(s);
  598.                                 break;
  599.             } else if (s->state != tcp_StateESTAB && s->state != tcp_StateESTCL ) {
  600.         s->err_msg = "Timeout, aborting";
  601.         tcp_abort(s);
  602.                 break;
  603.         }
  604.     }
  605.     }
  606.     /* do our various daemons */
  607.     if ( wattcpd ) (*wattcpd)();
  608. }
  609.  
  610.  
  611. /*
  612.  * Unthread a socket from the tcp socket list, if it's there
  613.  */
  614. static void tcp_unthread( tcp_Socket *ds )
  615. {
  616.     tcp_Socket *s, **sp;
  617.  
  618.         if (!ds->rdatalen || (ds->state > tcp_StateESTCL))
  619.         ds->ip_type = 0;                /* fail io */
  620.     ds->state = tcp_StateCLOSED;   /* tcp_tick needs this */
  621.     sp = &tcp_allsocs;
  622.     for (;;) {
  623.     s = *sp;
  624.     if ( s == ds ) {
  625.         *sp = s->next;
  626.             continue;           /* unthread multiple copies if necessary */
  627.     }
  628.     if ( !s ) break;
  629.     sp = &s->next;
  630.     }
  631. }
  632.  
  633. /*
  634.  * tcp_tick - called periodically by user application
  635.  *        - returns 1 when our socket closes
  636.  *        - called with socket parameter or NULL
  637.  */
  638. int tcp_tick( sock_type *s )
  639. {
  640.     in_Header *ip;
  641.     static longword timeout = 0;
  642.     static longword start = 0;
  643.  
  644. /*    int x; */
  645.     int packettype;
  646.  
  647.     /* finish off dead sockets */
  648.     if ( s ) {
  649.                 if (( s->tcp.ip_type == TCP_PROTO ) &&
  650.             ( s->tcp.state == tcp_StateCLOSED ) &&
  651.                         ( s->tcp.rdatalen == 0 )) {
  652.                 tcp_unthread( & s->tcp );
  653.         s->tcp.ip_type = 0;
  654.         }
  655.     }
  656.  
  657.  
  658.         /* plan our next retransmit */
  659.  
  660.     if ( !timeout )
  661.     timeout = make_timeout( tcp_RETRANSMITTIME );
  662.  
  663.     while ( (ip = (in_Header *)_eth_arrived( (word *) &packettype )) != NULL ) {
  664.     start = *realclock;
  665.  
  666.     switch ( packettype ) {
  667.     case /*0x800*/ 0x008 :
  668.         /* do IP */
  669.             if ( checksum(ip, in_GetHdrlenBytes(ip)) == 0xffff ) {
  670.         switch ( ip->proto ) {
  671.                 case TCP_PROTO :
  672.             tcp_handler(ip);
  673.             break;
  674.             case UDP_PROTO :
  675.             udp_handler(ip);
  676.             break;
  677.             case ICMP_PROTO :
  678.             icmp_handler(ip);
  679.             break;
  680.         }
  681.         } else  {
  682.         if (debug_on)
  683.             outs("IP Received BAD Checksum \n\r");
  684.         }
  685.         break;
  686.     case /*0x806*/ 0x608 :
  687.             /* do arp */
  688.         _arp_handler( (arp_Header *)ip );
  689.             break;
  690.     }
  691.     if (ip) _eth_free(ip);
  692.  
  693.     continue;
  694.     }
  695.     /* check for our outstanding packets */
  696.     tcp_Retransmitter();
  697.  
  698.         return( s->udp.ip_type );
  699. }
  700.  
  701. void tcp_set_debug_state( int x )
  702. {
  703.     debug_on = x;
  704. }
  705.  
  706. /* returns 1 if connection is established */
  707. int tcp_established( tcp_Socket *s )
  708. {
  709.         return( s->state >= tcp_StateESTAB );
  710. }
  711.  
  712. /*
  713.  * udp_write() handles fragmented UDP by assuming it'll be called
  714.  *     once for all fragments with no intervening calls.  This is
  715.  *     the case in sock_write().
  716.  * Handles upto a hair-under 32K datagrams.  Could be made to handle
  717.  *     upto a hair-under 64K easily...  wanna Erick?
  718.  * Might be possible to test 'offset' for non/zero fewer times to be
  719.  *     more efficient.  Might also be more efficient to use the old
  720.  *     UDP checksum() call when more_frags is false in the first frag
  721.  *     (i.e., not a fragmented dgram).
  722.  * Uses _mss to decide splits which defaults to 1400.  Could pack
  723.  *     more into an Ethernet packet.
  724.  */
  725. #define IP_MF 0x0020               // more fragments, net byte order
  726.  
  727. static udp_write( udp_Socket *s, byte *datap, int len, word offset )
  728. {
  729.         struct {                    // special pseudo header because need to
  730.         tcp_PseudoHeader ph;    //    compute checksum in two parts (may not
  731.                 word checksum2;         //    have all of datagram built at once).
  732.     } ph;
  733.     struct _pkt {
  734.     in_Header  in;
  735.     udp_Header udp;
  736.     int       data;
  737. /*    longword maxsegopt; */
  738.         } *pkt;
  739.     byte *dp;
  740.     in_Header *inp;
  741.     udp_Header *udpp;
  742.  
  743.     word maxlen;
  744.     int more_frags;
  745.     word origlen = len;
  746.  
  747.     pkt = (struct _pkt *)_eth_formatpacket(&s->hisethaddr, /*0x800*/ 8);
  748.  
  749.         if( offset ) {              // this is not the first fragment
  750.         dp = (byte *) &pkt->udp;    // data goes right after IP header
  751.         } else {
  752.         dp = (byte *) &pkt->data;
  753.         udpp = &pkt->udp;
  754.  
  755.         /* udp header */
  756.         udpp->srcPort = intel16( s->myport );
  757.         udpp->dstPort = intel16( s->hisport );
  758.                 udpp->checksum = 0;
  759.         udpp->length = intel16( UDP_LENGTH + len );
  760.     }
  761.     inp = &pkt->in;
  762.  
  763.     memset( inp, 0, sizeof( in_Header ));
  764.  
  765.     maxlen = _mss & 0xFFF8;             // make a multiple of 8
  766.     if( !offset ) maxlen -= UDP_LENGTH; // note UDP_LENGTH is 8, so ok
  767.  
  768.     if( len > maxlen ) {
  769.                 len = maxlen;
  770.         more_frags = 1;
  771.         } else more_frags = 0;
  772.  
  773.     inp->length = intel16( sizeof(in_Header) +
  774.                                      (offset ? 0 : UDP_LENGTH) + len );
  775.     movmem(datap, dp, len );
  776.  
  777.     /* internet header */
  778.         inp->ver = 4;
  779.     inp->hdrlen = 5;
  780.     inp->tos = 0;
  781. /* inp->vht = 0x4500;*/   /* version 4, hdrlen 5, tos 0 */
  782.  /* if offset non-zero, then is part of a prev datagram so don't incr ID */
  783.     inp->identification = intel16( offset ? ip_id : ++ip_id );   /* was post inc */
  784. //    inp->frag = 0;
  785.     inp->frags = (offset ? intel16((offset + UDP_LENGTH) >> 3) : 0);
  786.     if(more_frags) inp->frags |= IP_MF;
  787.     inp->ttl = 254;
  788.     inp->proto = UDP_PROTO;    /* udp */
  789. /* inp->ttlProtocol = (250<<8) + 6; */
  790.     inp->checksum = 0;
  791.         inp->source = intel( s->myaddr );
  792.     inp->destination = intel( s->hisaddr );
  793.     inp->checksum = ~checksum( inp, sizeof(in_Header));
  794.  
  795.  
  796.     /* compute udp checksum if desired */
  797.     if(!offset) {  // only first of frags has UDP header for entire UDP dgram
  798.                 if ( s->sock_mode & UDP_MODE_NOCHK )
  799.         udpp->checksum = 0;
  800.         else {
  801.         ph.ph.src = inp->source;    /* already INTELled */
  802.         ph.ph.dst = inp->destination;
  803.         ph.ph.mbz = 0;
  804.         ph.ph.protocol = UDP_PROTO;    /* udp */
  805.         ph.ph.length = udpp->length;    /* already INTELled */
  806.  
  807.           /* can't use since may not have the whole dgram built at once */
  808. //        ph.checksum = checksum(&pkt->udp, intel16(ph.length));
  809.                     /* this way handles it */
  810.             ph.ph.checksum = checksum(&pkt->udp, UDP_LENGTH);
  811.                         ph.checksum2 = checksum(datap, origlen);
  812.  
  813.         udpp->checksum =  ~checksum(&ph, sizeof(ph));
  814.         }
  815.     }
  816.     
  817.     if (_dbugxmit) (*_dbugxmit)( (sock_type*)s, inp, udpp, 0 );
  818.         _eth_send( intel16( inp->length ));
  819.  
  820.     return ( len );
  821. }
  822.  
  823. /*
  824.  * udp_read - read data from buffer, does large buffering
  825.  */
  826. static int udp_read( udp_Socket *s, byte *datap, int maxlen )
  827. {
  828.     int x;
  829.  
  830.     if (maxlen < 0) maxlen = MAXINT;
  831.         if (( x = s->rdatalen ) > 0) {
  832.     if ( x > maxlen ) x = maxlen;
  833.     if ( x > 0 ) {
  834.             if (datap) movmem( s->rdata, datap, x );
  835.         if ( s->rdatalen -= x )
  836.                 movmem( s->rdata + x, s->rdata, s->rdatalen);
  837.     }
  838.         }
  839.     return( x );
  840. }
  841.  
  842. void _udp_cancel( in_Header *ip )
  843. {
  844.     int len;
  845.     udp_Header *up;
  846.     udp_Socket *s;
  847.  
  848.     /* match to a udp socket */
  849.         len = in_GetHdrlenBytes(ip);
  850.     up = (udp_Header *)((byte *)ip + len);    /* udp frame pointer */
  851.  
  852.     /* demux to active sockets */
  853.     for ( s = udp_allsocs; s; s = s->next )
  854.         if ( s->hisport != 0 &&
  855.              intel16( up->dstPort ) == s->hisport &&
  856.              intel16( up->srcPort ) == s->myport &&
  857.              intel( ip->destination ) == s->hisaddr ) break;
  858.         if ( !s ) {
  859.     /* demux to passive sockets */
  860.     for ( s = udp_allsocs; s; s = s->next )
  861.         if ( s->hisport == 0 && intel16( up->dstPort ) == s->myport ) break;
  862.     }
  863.     if (s) {
  864.         s->rdatalen = 0;
  865.     s->ip_type = 0;
  866.     }
  867. }
  868.  
  869. void *_tcp_lookup( longword hisip, word hisport, word myport )
  870. {
  871.         tcp_Socket *s;
  872.     for ( s = tcp_allsocs; s; s = s->next ) {
  873.         if ( ( myport == s->myport ) &&         /* always unique under WATTCP */
  874.              ( hisport == s->hisport ) &&
  875.              ( hisip == s->hisaddr ))
  876.                 return( s );
  877.     }
  878.         return( NULL );
  879. }
  880.  
  881. void _tcp_cancel( in_Header *ip, int code, char *msg, longword dummyip )
  882. {
  883.     static int in_icmp_redirect = 0;            // smart@actrix.gen.nz
  884.     int len;
  885.     tcp_Socket *s;
  886.     tcp_Header *tp;
  887.  
  888.     len = in_GetHdrlenBytes(ip);    /* check work */
  889.  
  890.     tp = (tcp_Header *)((byte *)ip + len);    /* tcp frame pointer */
  891.  
  892.     /* demux to active sockets */
  893.     for ( s = tcp_allsocs; s; s = s->next ) {
  894.         if ( intel16( tp->srcPort) == s->myport &&
  895.              intel16( tp->dstPort ) == s->hisport &&
  896.              intel( ip->destination ) == s->hisaddr ) {
  897.                 switch (code) {
  898.                                         /* halt it */
  899.                     case  1 : if (( s->stress ++ > s->rigid ) &&
  900.                                   ( s->rigid < 100 )) {
  901.                                   s->err_msg = (msg) ?
  902.                                     msg : "ICMP closed connection";
  903.                                   s->rdatalen = s->datalen = 0;
  904.                                   s->unhappy = false;
  905.                                   tcp_abort( s );
  906.                 /*      if (s->dataHandler) s->dataHandler(s, 0, -1); */
  907.                                   break;
  908.                               }
  909.                                                             // follow through to next case
  910.  
  911.                                         /* slow it down */
  912.                     case  2 : s->cwindow = 1;
  913.                               s->wwindow = 1;
  914.                               s->rto <<= 2;
  915.                               s->vj_sa <<= 2;
  916.                               s->vj_sd <<= 2;
  917.                               break;
  918.                                         /* icmp redirect for host */
  919.                     case  5 : /* save his NEW network address */
  920.                         /* Dummy is passed in NW form need to intel! */
  921.                         /* This was a bug fixed QVS - smart@actrix.gen.nz */
  922.                               if (!in_icmp_redirect)
  923.                               {
  924.                                   in_icmp_redirect = 1;
  925.                                   _arp_resolve(intel(dummyip), &s->hisethaddr, 0);
  926.                                   in_icmp_redirect = 0;
  927.                               }
  928.                               break;
  929.                                 }
  930.         }
  931.         }
  932. }
  933.  
  934. static int tcp_read( tcp_Socket *s, byte *datap, int maxlen )
  935. {
  936.     int x;
  937.  
  938.         if (maxlen < 0 ) maxlen = MAXINT;
  939.     if (( x = s->rdatalen) > 0) {
  940.     if ( x > maxlen ) x = maxlen;
  941.         if ( x > 0 ) {
  942.             if (datap) movmem( s->rdata, datap, x );
  943.             if (( s->rdatalen -= x ) > 0 ) {
  944.                 movmem( s->rdata + x, s->rdata, s->rdatalen );
  945.                 tcp_sendsoon( s );   /* update the window */
  946.             } else
  947.                 tcp_send( s, __LINE__ );      /* update window el-pronto */
  948.     }
  949.         } else if ( s->state == tcp_StateCLOSWT )
  950.         tcp_close( s );
  951.         return( x );
  952. }
  953.  
  954. /*
  955.  * Write data to a connection.
  956.  * Returns number of bytes written, == 0 when connection is not in
  957.  * established state.
  958.  */
  959. static int tcp_write( tcp_Socket *s, byte *dp, int len )
  960. {
  961.     int x;
  962.  
  963.     if (len < 0 ) len = MAXINT;
  964.     /* no longer uses tcp_MaxData */
  965.     if ( s->state != tcp_StateESTAB ) len = 0;
  966.     if ( len > (x = s->maxrdatalen - s->datalen) ) len = x;
  967.     if ( len > 0 ) {
  968.         movmem( dp, s->data + s->datalen, len );
  969.  
  970.     s->datalen += len;
  971.     s->unhappy = true;    /* redundant because we have outstanding data */
  972.  
  973.         if ( s->sock_mode & TCP_LOCAL )
  974.             s->sock_mode &= ~TCP_LOCAL;
  975.         else {
  976.             if ( s->sock_mode & TCP_MODE_NONAGLE ) {
  977.                 tcp_send( s, __LINE__ );
  978.                         } else {
  979.                 /* transmit if first data or reached MTU */
  980.                 /* not true MTU, but better than nothing */
  981.                 if (( s->datalen == len ) || ( s->datalen > (s->mss)/2 ))
  982.                     tcp_send( s, __LINE__ );
  983.                 else
  984.                     tcp_sendsoon( s );
  985.             }
  986.     }
  987.     }
  988.  
  989.         return ( len );
  990. }
  991.  
  992. /*
  993.  * Send pending data
  994.  */
  995. static void tcp_Flush( tcp_Socket *s )
  996. {
  997.     if ( s->datalen > 0 ) {
  998.                 s->flags |= tcp_FlagPUSH;
  999.         tcp_send(s, __LINE__);
  1000.     }
  1001. }
  1002.  
  1003. /*
  1004.  * Handler for incoming packets.
  1005.  */
  1006. static void udp_handler( in_Header *ip )
  1007. {
  1008.     udp_Header *up;
  1009.     tcp_PseudoHeader ph;
  1010.     word len;
  1011.     byte *dp;
  1012.     longword temp;
  1013.     udp_Socket *s;
  1014.  
  1015. #ifdef __UDP_PASSIVE_SOCKET_BUG__
  1016.     int need_arp = 0; /* must be auto, 98.04.03 */
  1017. #endif
  1018.  
  1019.     temp = intel( ip->destination );
  1020.  
  1021.     // temp = ip number
  1022.     //     or 255.255.255.255
  1023.     //     or sin_mask.255.255
  1024.  
  1025.     if ( ((~temp & ~sin_mask) != 0) &&  /* not a broadcast packet*/
  1026.         ((( temp - my_ip_addr) > multihomes )   /* not my address */
  1027.         && my_ip_addr))                 /* and I know my address */
  1028.             return;
  1029.  
  1030.  
  1031.     len = in_GetHdrlenBytes(ip);
  1032.     up = (udp_Header *)((byte *)ip + len);    /* udp segment pointer */
  1033.     len = intel16( up->length );
  1034.  
  1035.     /* demux to active sockets */
  1036.     for ( s = udp_allsocs; s; s = s->next ) {
  1037.         if ( s->safetysig != SAFETYUDP ) {
  1038.             if (debug_on) outs("chain error in udp\r\n");
  1039.         }
  1040.         if ( (s->hisport != 0) &&
  1041.              (intel16( up->dstPort ) == s->myport) &&
  1042.              (intel16( up->srcPort ) == s->hisport) &&
  1043. #ifdef __UDP_HANDLER_OPTIMIZATION__
  1044.              ((temp & sin_mask)  == (s->myaddr & sin_mask)) &&
  1045. #else
  1046.              ((intel( ip->destination ) & sin_mask)  == (s->myaddr & sin_mask)) &&
  1047. #endif
  1048.              (intel( ip->source ) == s->hisaddr )) break;
  1049.     }
  1050.     if (_dbugrecv) (*_dbugrecv)( (sock_type*)s, ip, up, 0);
  1051.     if ( !s ) {
  1052.         /* demux to passive sockets */
  1053.     for ( s = udp_allsocs; s; s = s->next )
  1054.             if ( ((s->hisaddr == 0) || (s->hisaddr == 0xffffffffuL))
  1055.               && intel16( up->dstPort ) == s->myport ) {
  1056.  
  1057.                 // do we record this information ???
  1058.                 if ( s->hisaddr == 0 ) {
  1059.             s->hisaddr = intel( ip->source );
  1060.             s->hisport = intel16( up->srcPort );
  1061.  
  1062. /* Dashui Zhou 13/10/1998 bug fix applied, original line is moved to the end of the
  1063.  * function and replaced here by the setting of the new flag.
  1064.  * The problem was that an ARP answer packet overwrites the first datagram
  1065.  * that arrives at a newly opend passive UDP socket. */
  1066. #ifdef __UDP_PASSIVE_SOCKET_BUG__
  1067.             need_arp = 1; /* remember we need arp and postpone arp action. */
  1068. #else
  1069.          _arp_resolve(intel(ip->source), &s->hisethaddr, 0);
  1070. #endif
  1071.  
  1072.             // take on value of expected destination unless it
  1073.             // is broadcast
  1074.  
  1075. #ifdef __UDP_HANDLER_OPTIMIZATION__
  1076.             if ( (~temp & ~sin_mask) != 0 )
  1077. #else
  1078.             if ( (~ip->destination & ~sin_mask) != 0 )
  1079. #endif
  1080.  
  1081.             s->myaddr = intel( ip->destination );
  1082.         }
  1083.         break;
  1084.         }
  1085.     }
  1086.     if ( !s ) {
  1087.     /* demux to broadcast sockets */
  1088.     for ( s = udp_allsocs; s; s = s->next )
  1089.  
  1090. #ifdef __UDP_BROADCAST_BUG__
  1091. /*
  1092.  * Explanation
  1093.  * ===========
  1094.  * 's->hisaddr' contains the address of the host we communicate with
  1095.  * through this port (thanks to udp_open()). So, if the socket was not
  1096.  * opened in broadcast mode (s->hisaddr == -1uL) it will ignore broadcasts
  1097.  * to this port. (not really my idea of a broadcast).
  1098.  * This can be changed by replacing 's->hisaddr' by 'temp', which contains
  1099.  * the destination address of the packet we are currently trying to match
  1100.  * with a port.
  1101.  */
  1102.         if ( (temp == 0xffffffffuL) &&
  1103. #else
  1104.         if ( (s->hisaddr == 0xffffffffuL) &&
  1105. #endif
  1106.  
  1107.          (intel16( up->dstPort ) == s->myport )) break;
  1108.     }
  1109.  
  1110.     if ( !s ) {
  1111.     if (debug_on) outs("discarding...");
  1112.     return;
  1113.     }
  1114.  
  1115.     // these parameters are used for things other than just checksums
  1116.     ph.src = ip->source;    /* already INTELled */
  1117.     ph.dst = ip->destination;
  1118.     ph.mbz = 0;
  1119.     ph.protocol = UDP_PROTO;
  1120.     ph.length = up->length;
  1121.     if ( up->checksum ) {
  1122.     ph.checksum =  checksum(up, len);
  1123.     if (checksum(&ph, sizeof( tcp_PseudoHeader)) != 0xffff)
  1124.         return;
  1125.     }
  1126.  
  1127.     /* process user data */
  1128.     if ( (len -= UDP_LENGTH ) > 0) {
  1129.     dp = (byte *)( up );
  1130.         if (s->dataHandler) s->dataHandler( s, &dp[ UDP_LENGTH ], len , &ph, up);
  1131.     else {
  1132.             if (len > s->maxrdatalen ) len = s->maxrdatalen;
  1133.         movmem( &dp[ UDP_LENGTH ], s->rdata, len );
  1134.         s->rdatalen = len;
  1135.     }
  1136.     }
  1137.  
  1138. #ifdef __UDP_PASSIVE_SOCKET_BUG__
  1139.     /* Get his MAC address before return, 98.04.03 */
  1140.     if (need_arp) _arp_resolve(intel(ip->source),&s->hisethaddr,0);
  1141. #endif
  1142.  
  1143. }
  1144.  
  1145. static void tcp_handler( in_Header *ip )
  1146. {
  1147.     tcp_Header *tp;
  1148.     tcp_PseudoHeader ph;
  1149.     int len;
  1150. /*    byte *dp;  */
  1151.         int diff;
  1152.         tcp_Socket *s;
  1153.     word flags;
  1154.         long diffticks, ldiff;    /* must be signed */
  1155.         long scheduleto;
  1156.  
  1157.  
  1158.         if ( (longword)(intel( ip->destination ) - my_ip_addr) > multihomes )
  1159.         return;
  1160.  
  1161.     len = in_GetHdrlenBytes(ip);
  1162.         len = intel16( ip->length ) - len;        /* len of tcp data */
  1163.  
  1164.     len = in_GetHdrlenBytes(ip);
  1165.     tp = (tcp_Header *)((byte *)ip + len);    /* tcp frame pointer */
  1166.     len = intel16( ip->length ) - len;        /* len of tcp data */
  1167.     flags = intel16( tp->flags );
  1168.  
  1169.         if (debug_on > 1) {
  1170.             mono[160]++;
  1171.             colour[160]++;
  1172.             mono[162] = colour[162] = (flags & tcp_FlagSYN) ? 'S' : ' ';
  1173.             mono[164] = colour[164] = (flags & tcp_FlagACK) ? 'A' : ' ';
  1174.             mono[166] = colour[166] = (flags & tcp_FlagFIN) ? 'F' : ' ';
  1175.                         mono[168] = colour[168] = (flags & tcp_FlagRST) ? 'R' : ' ';
  1176.         }
  1177.  
  1178.         /* demux to active sockets */
  1179.     for ( s = tcp_allsocs; s; s = s->next ) {
  1180.         if ( s->safetysig != SAFETYTCP ) {
  1181.             if (debug_on) outs("chain error in tcp\r\n");
  1182.                 }
  1183.     if ( s->hisport != 0 &&
  1184.          intel16( tp->dstPort ) == s->myport &&
  1185.          intel16( tp->srcPort ) == s->hisport &&
  1186.              intel( ip->destination )   == s->myaddr     &&
  1187.          intel( ip->source ) == s->hisaddr ) break;
  1188.     }
  1189.         if ( !s && (flags & tcp_FlagSYN)) {
  1190.     /* demux to passive sockets, must be a new session */
  1191.     for ( s = tcp_allsocs; s; s = s->next )
  1192.             if ((s->hisport == 0) && (intel16( tp->dstPort ) == s->myport )) {
  1193.                 s->myaddr = intel( ip->destination );
  1194.         break;
  1195.                         }
  1196.     }
  1197.  
  1198.  
  1199.     if (_dbugrecv) (*_dbugrecv)( (sock_type*)s, ip, tp, 0 );
  1200.     if ( !s ) {
  1201.         if (!(flags & tcp_FlagRST)) tcp_rst( ip, tp );
  1202.     return;
  1203.     }
  1204.  
  1205.     ph.src = ip->source;    /* already INTELled */
  1206.     ph.dst = ip->destination;
  1207.     ph.mbz = 0;
  1208.     ph.protocol = TCP_PROTO;
  1209.         ph.length = intel16( len );
  1210.     ph.checksum =  checksum(tp, len);
  1211.     if ( checksum(&ph, sizeof(ph)) != 0xffff ) {
  1212.      if (debug_on) outs("bad tcp checksum \n\r");
  1213.  
  1214.          /* tester */
  1215.          ph.checksum =  checksum(tp, len);
  1216.          checksum(&ph, sizeof(ph));
  1217.  
  1218.                  tcp_sendsoon( s );
  1219.      return;
  1220.     }
  1221.  
  1222. /* reset code */
  1223.     if ( flags & tcp_FlagRST ) {
  1224.     if (debug_on) outs("\7\7\7\7\7\7\7connection reset\n");
  1225.         s->rdatalen = s->datalen = 0;
  1226.         s->err_msg = "Remote reset connection";
  1227.     s->state = tcp_StateCLOSED;
  1228. /*    if (s->dataHandler) s->dataHandler(s, 0, -1); */
  1229.     tcp_unthread(s);
  1230.     return;
  1231.     }
  1232.  
  1233.     if ( sock_inactive )
  1234.         s->inactive_to = set_timeout( sock_inactive );
  1235.  
  1236.  
  1237.     /* update our retransmission stuff */
  1238.         /* new algorithms */
  1239.     if (s->karn_count == 2) {
  1240.         s->karn_count = 0;
  1241. #ifdef DEBUG
  1242.                 if (debug_on > 1 ) printf("finally got it safely zapped from %u to ????\n\r",s->unacked);
  1243. #endif /* DEBUG */
  1244.     } else {
  1245.         if ( s->vj_last ) {
  1246.             /* unnecessary to use unhappy || s->datalen ) */
  1247.             if ((diffticks = set_ttimeout( 0 ) - s->vj_last) >= 0 ) {
  1248.                 /* we ignore the overnight case */
  1249.                                 diffticks -= (longword)( s->vj_sa >> 3 );
  1250.                 s->vj_sa += (int)diffticks;
  1251.                 if (diffticks < 0)
  1252.                     diffticks = - diffticks;
  1253.                 diffticks -= (s->vj_sd >> 2);
  1254.                 s->vj_sd += (int)diffticks;
  1255.                 if (s->vj_sa > MAXVJSA) s->vj_sa = MAXVJSA;
  1256.                 if (s->vj_sd > MAXVJSD) s->vj_sd = MAXVJSD;
  1257.             }
  1258.                         /* only recompute rtt hence rto after success */
  1259.             s->rto = 1 + ((s->vj_sa >> 2) + (s->vj_sd)) >> 1 ;
  1260. #ifdef DEBUG
  1261.             if (debug_on > 1 ) printf("rto  %u  sa  %u  sd  %u   cwindow %u  wwindow %u  unacked %u\n",
  1262.                                 s->rto, s->vj_sa, s->vj_sd, s->cwindow, s->wwindow, s->unacked );
  1263. #endif /* DEBUG */
  1264.     }
  1265.         s->karn_count = 0;
  1266.         if ( s->wwindow != 255 ) {
  1267.             if ( s->wwindow++ >= s->cwindow ) {
  1268.                 if ( s->cwindow != 255 )
  1269.                                         s->cwindow ++;
  1270.       /* tcpwinfix
  1271.        *    Movement of the next line *seems* to fix the failure of the TCP
  1272.        *    send window to open up (which makes TCP writes very slow, as
  1273.        *    seen with some previous releases of WatFTP), though it's been
  1274.        *    a long time since I made this change (today is 96.09.24) and
  1275.        *    I'm not sure how confident I was even then that it was correct.
  1276.        *    Also I don't have any description of the VJ algorithm and don't
  1277.        *    really understand this code all that well, but some time ago
  1278.              *    this seemed to be the right thing to do and seems to work.
  1279.        *    That said, if I'm wrong, I hope I haven't broken things worse :-)
  1280.        *    There is one other place, also marked 'tcpwinfix' above in this
  1281.        *    file, and those are the only two changes I made for this bug
  1282.              *    which may need undoing if I'm wrong. -- mdurkin
  1283.        */
  1284.                 s->wwindow = 0;  /* mdurkin -- added 95.05.02 */
  1285.             }
  1286. /*            s->wwindow = 0;    /* mdurkin -- removed 95.05.02 */
  1287.         }
  1288.     }
  1289.         /* all new */
  1290.     scheduleto = set_ttimeout( s->rto + 2 );
  1291.     if ( s->rtt_time < scheduleto ) s->rtt_time = scheduleto;
  1292.  
  1293.  
  1294.     switch ( s->state ) {
  1295.  
  1296.     case tcp_StateLISTEN:    /* accepting SYNs */
  1297.             /* save his ethernet address */
  1298.                         if ( _pktipofs )
  1299.                 movmem(&((((eth_Header *)ip) - 1)->source), &s->hisethaddr, sizeof(eth_address));
  1300.             if ( flags & tcp_FlagSYN ) {
  1301.  
  1302.                                 if ( ip->tos > s->tos )
  1303.                     s->tos = ip->tos;
  1304.                 else if ( ip->tos < s->tos ) {
  1305.                     /* RFC 793 says we should close connection */
  1306.                     /* we best not do that while SunOS ignores TOS */
  1307.                 }
  1308.  
  1309.                                 s->acknum = intel( tp->seqnum ) + 1;
  1310.         s->hisport = intel16( tp->srcPort );
  1311.         s->hisaddr = intel( ip->source );
  1312.         s->flags = tcp_FlagSYN | tcp_FlagACK;
  1313.                 s->state = tcp_StateSYNREC;
  1314.         s->unhappy = true;
  1315.                 tcp_send(s, __LINE__);    /* we must respond immediately */
  1316.  
  1317.         s->timeout = set_timeout( tcp_TIMEOUT );
  1318.             } else
  1319.         tcp_rst( ip , tp );  /* send a reset */
  1320.  
  1321.             return;
  1322.  
  1323.     case tcp_StateSYNSENT:  /* added ACK Section */
  1324.         if ( flags & tcp_FlagSYN ) {
  1325.  
  1326.                 if ( ip->tos > s->tos )
  1327.                     s->tos = ip->tos;
  1328.                 else if ( ip->tos < s->tos ) {
  1329.                                         /* RFC 793 says we should close connection */
  1330.                     /* we best not do that while SunOS ignores TOS */
  1331.                 }
  1332.  
  1333.                 s->flags = tcp_FlagACK;
  1334.         s->timeout = set_timeout( tcp_TIMEOUT );
  1335.  
  1336.         /* FlagACK means connection established, else SYNREC */
  1337.         if ( flags & tcp_FlagACK) {
  1338.                 /* but is it for the correct session ? */
  1339.                 if (tp->acknum == intel(s->seqnum + 1)) {
  1340.                 s->state = tcp_StateESTAB;
  1341.                 s->seqnum++;    /* good increment */
  1342.                                 s->acknum = intel( tp->seqnum  ) + 1;   /* 32 bits */
  1343.                 tcp_ProcessData(s, tp, len, &ph);    /* someone may try it */
  1344.                 s->unhappy = true;             /* rely on their attempts */
  1345.                 tcp_send( s, __LINE__ );
  1346.             } else {
  1347.                 /* wrong ack, force a RST and resend SYN soon*/
  1348.                 s->flags = tcp_FlagRST;
  1349.                                 s->unhappy = true;
  1350.                 tcp_send( s, __LINE__ );
  1351.                 s->flags = tcp_FlagSYN;
  1352.                 tcp_send( s, __LINE__ );
  1353.             }
  1354.         } else {
  1355.             s->acknum++;
  1356.             s->state = tcp_StateSYNREC;
  1357.                     return;
  1358.         }
  1359.             } else
  1360.                 tcp_rst( ip, tp );
  1361.         break;
  1362.  
  1363.     case tcp_StateSYNREC:    /* recSYNSENT, sentACK, waiting  EST */
  1364.         if ( flags & tcp_FlagSYN ) {
  1365.         s->flags = tcp_FlagSYN | tcp_FlagACK;
  1366.         s->unhappy = true;
  1367.                 tcp_send(s, __LINE__);
  1368.         s->timeout = set_timeout( tcp_TIMEOUT );
  1369.                                 return;
  1370.         }
  1371.         if ( (flags & tcp_FlagACK) && (intel( tp->acknum ) == (s->seqnum + 1))) {
  1372.                 if ( (s->window = intel16( tp->window )) > 0x7fff )
  1373.                     s->window = 0x7fff;
  1374.         s->flags = tcp_FlagACK;
  1375.                 s->state = tcp_StateESTAB;
  1376.                 s->seqnum++;
  1377.                 s->timeout = 0;     /* never timeout */
  1378.                                 s->unhappy = false;
  1379.                 return;
  1380.         }
  1381.  
  1382.             break;
  1383.     case tcp_StateESTAB:
  1384.         case tcp_StateESTCL:
  1385.         case tcp_StateCLOSWT:
  1386.  
  1387.             /* handle lost SYN */
  1388.             if ((flags & tcp_FlagSYN) && (flags & tcp_FlagACK)) {
  1389.                                 tcp_send( s, __LINE__ );
  1390.                 return;
  1391.             }
  1392.  
  1393.         if ( !(flags & tcp_FlagACK)) return;  /* must ack somthing */
  1394.             if ( flags & tcp_FlagSYN ) {
  1395.                 tcp_rst( ip , tp );
  1396.                 return;
  1397.             }
  1398.             s->timeout = 0l;    /* we do not timeout at this point */
  1399.  
  1400.         /* process ack value in packet - but only if it falls
  1401.          * within current window */
  1402.  
  1403.         ldiff = intel( tp->acknum ) - s->seqnum;
  1404.         diff = (int) ldiff;
  1405.  
  1406.             if ( ldiff >= 0 && diff <= s->datalen ) {
  1407.         s->datalen -= diff;
  1408.                 s->unacked -= diff;
  1409.                                 if (s->datalen < 0) s->datalen = 0; /* remote proto error */
  1410.                 if ( s->queuelen ) {
  1411.                     s->queue += diff;
  1412.                     s->queuelen -= diff;
  1413.                 } else
  1414.                     movmem(s->data + diff, s->data, s->datalen );
  1415.         s->seqnum += ldiff;
  1416.             } else {
  1417. #ifdef DEBUG
  1418.         if(debug_on >1) printf("tcphandler confused so set unacked back to 0 from %u\n",s->unacked);
  1419. #endif DEBUG
  1420.                 s->unacked = 0;
  1421.             }
  1422.                         if (s->unacked < 0) s->unacked = 0;
  1423.  
  1424.         s->flags = tcp_FlagACK;
  1425.         tcp_ProcessData(s, tp, len, &ph);
  1426.  
  1427.             if (( flags & tcp_FlagFIN ) && (s->state != tcp_StateCLOSWT )
  1428.                 && ( s->acknum == intel( tp->seqnum ))) {
  1429.                                 s->acknum ++;
  1430.                 if ( ! s->err_msg ) s->err_msg = "Connection closed";
  1431.                 s->state = tcp_StateCLOSWT;
  1432.                 tcp_send( s, __LINE__ );
  1433.                 s->state = tcp_StateLASTACK;
  1434.                 s->flags |= tcp_FlagFIN;
  1435.                 s->unhappy = true;
  1436.             }
  1437.  
  1438. #ifdef __SPURIOUS_ACK_BUG__
  1439. /*
  1440.  * Eliminate the spurious ACK messages bug.
  1441.  * For the window update, the length should be the
  1442.  * data length only, so exclude the TCP header size
  1443.  *  -- Joe <jdhagen@itis.com> (this helped alot -gv)
  1444.  */
  1445.             len -= tcp_GetDataOffset(tp) << 2;
  1446. #endif
  1447.  
  1448.             if ( diff > 0 || len > 0 ) {
  1449.                                 /* need to update window, but how urgent ??? */
  1450.                                 if ( diff > 0 || (len > (s->mss >> 1))) {
  1451.                                         tcp_send( s, __LINE__ );
  1452.                                 } else
  1453.                     tcp_sendsoon( s );
  1454.  
  1455.             }
  1456.             if ( s->state == tcp_StateESTCL )
  1457.                 tcp_close( s );
  1458.             return;
  1459.  
  1460.     case tcp_StateFINWT1:
  1461.         /* They have not necessarily read all the data yet, we must
  1462.            still supply it as requested */
  1463.  
  1464.         ldiff = intel( tp->acknum ) - s->seqnum;
  1465.         diff = (int) ldiff;
  1466.         if ( ldiff >= 0 && diff <= s->datalen ) {
  1467.         s->datalen -= diff;
  1468.                 s->unacked -= diff;
  1469.                                 if (s->datalen < 0) s->datalen = 0;
  1470.                 if ( s->queuelen ) {
  1471.                     s->queue += diff;
  1472.                     s->queuelen -= diff;
  1473.                 } else
  1474.                     movmem(s->data + diff, s->data, s->datalen );
  1475.         s->seqnum += ldiff;
  1476.                 if (ldiff == 0 || s->unacked < 0) s->unacked = 0;
  1477.  
  1478.         }
  1479.  
  1480.         /* they may still be transmitting data, we must read it */
  1481.  
  1482.         tcp_ProcessData(s, tp, len, &ph);
  1483.  
  1484.         /* check if other tcp has acked all sent data and is ready
  1485.            to change states */
  1486.  
  1487.             if ( (flags & (tcp_FlagFIN|tcp_FlagACK) ) == (tcp_FlagFIN|tcp_FlagACK)) {
  1488.         /* trying to do similtaneous close */
  1489.         if (( intel( tp->acknum ) >= s->seqnum + 1 ) &&
  1490.             ( intel( tp->seqnum) == s->acknum )) {
  1491.             s->seqnum++;
  1492. // we shouldn't be inc'ing the ack
  1493. //                  s->acknum++;
  1494.                     s->flags = tcp_FlagACK;
  1495.                     tcp_send( s, __LINE__ );
  1496.                     s->unhappy = false;
  1497.                     s->timeout = set_timeout( 2 );
  1498.                     s->state = tcp_StateCLOSED;
  1499.         }
  1500.         } else if ( flags & tcp_FlagACK ) {
  1501.         /* other side is legitimately acking our fin */
  1502.         if (( intel( tp->acknum ) == s->seqnum + 1 ) &&
  1503.             ( intel( tp->seqnum ) == s->acknum ) &&
  1504.             (  s->datalen == 0 )) {
  1505.                         s->seqnum++;
  1506. // they are just acking our seq num, not sending more data for us to ack
  1507. //                      s->acknum++;
  1508.                         s->state = tcp_StateFINWT2;
  1509.                                                 s->timeout = set_timeout( 3 );
  1510.                         s->unhappy = false; /* we don't send anything */
  1511.         }
  1512.         }
  1513.         break;
  1514.  
  1515.     case tcp_StateFINWT2:
  1516.  
  1517.         /* they may still be transmitting data, we must read it */
  1518.         tcp_ProcessData(s, tp, len, &ph);
  1519.  
  1520.             if ((flags & (tcp_FlagACK | tcp_FlagFIN)) ==
  1521.                   (tcp_FlagACK | tcp_FlagFIN)) {
  1522.                 if (( intel( tp->acknum ) == s->seqnum) &&
  1523.             ( intel( tp->seqnum ) == s->acknum )) {
  1524.             s->acknum++;
  1525.             s->flags = tcp_FlagACK;
  1526.                     tcp_send( s, __LINE__ );
  1527.             s->unhappy = false;    /* we don't send anything */
  1528.             s->timeout = set_timeout( 2 );
  1529.                                         s->state = tcp_StateCLOSED;
  1530.                     return;
  1531.                 }
  1532.         }
  1533.         break;
  1534.  
  1535.     case tcp_StateCLOSING:
  1536.         if ((flags & (tcp_FlagACK | tcp_FlagFIN)) == tcp_FlagACK ) {
  1537.         if (( tp->acknum == intel(s->seqnum) ) &&
  1538.             ( tp->seqnum == intel(s->acknum))) {
  1539.             s->state = tcp_StateTIMEWT;
  1540.             s->timeout = set_timeout( tcp_TIMEOUT );
  1541.             s->unhappy = false;
  1542.         }
  1543.         }
  1544.         break;
  1545.  
  1546.     case tcp_StateLASTACK:
  1547.         if ( flags & tcp_FlagFIN ) {
  1548.         /* they lost our two packets, back up */
  1549.         s->flags = tcp_FlagACK | tcp_FlagFIN;
  1550.                 tcp_send( s, __LINE__ );
  1551.                 s->unhappy = TRUE;  /* FALSE; */
  1552.                 return;
  1553.         } else {
  1554.         if (( intel( tp->acknum ) == (s->seqnum + 1 )) &&
  1555.             ( intel( tp->seqnum ) == s->acknum )) {
  1556.             s->state = tcp_StateCLOSED;     /* no 2msl necessary */
  1557.             s->unhappy = false;             /* we're done */
  1558.                         return;
  1559.             }
  1560.         }
  1561.         break;
  1562.  
  1563.     case tcp_StateTIMEWT:
  1564.             if ( flags & (tcp_FlagACK | tcp_FlagFIN) == (tcp_FlagACK | tcp_FlagFIN)) {
  1565.                 /* he needs an ack */
  1566.                 s->flags = tcp_FlagACK;
  1567.                 tcp_send( s, __LINE__ );
  1568.                 s->unhappy = false;
  1569.                                 s->state = tcp_StateCLOSED;     /* support 2 msl in rst code */
  1570.             }
  1571.             break;
  1572.     }
  1573.     if (s->unhappy) tcp_sendsoon(s);
  1574. }
  1575.  
  1576. /*
  1577.  * Process the data in an incoming packet.
  1578.  * Called from all states where incoming data can be received: established,
  1579.  * fin-wait-1, fin-wait-2
  1580.  */
  1581. static void tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len,
  1582.                                                    tcp_PseudoHeader *ph)
  1583. {
  1584.     long ldiff;
  1585.     int diff, x;
  1586.     word flags;
  1587.     byte *dp;
  1588.  
  1589.         word *options, numoptions, opt_temp;
  1590.  
  1591.     if ( s->stress > 0 ) s->stress--;
  1592.  
  1593.     if ( (s->window = intel16( tp->window )) > 0x7fff )
  1594.         s->window = 0x7fff;
  1595.  
  1596.     flags = intel16( tp->flags );
  1597.     ldiff = s->acknum - intel( tp->seqnum );
  1598.  
  1599.     if ( flags & tcp_FlagSYN ) ldiff--;  /* back up to 0 */
  1600.     diff = (int) ldiff;
  1601.  
  1602.     /* find the data portion */
  1603.     x = tcp_GetDataOffset(tp) << 2;    /* quadword to byte format */
  1604.     dp = (byte *)tp + x;
  1605.  
  1606.     /* process those options */
  1607.     if ( (numoptions = x - sizeof( tcp_Header )) != 0 ) {
  1608.     options = (word *)((byte *)(tp) + sizeof( tcp_Header));
  1609.     while ( numoptions-- > 0 ) {
  1610.         switch ( *options++ ) {
  1611.         case  0 : numoptions = 0;    /* end of options */
  1612.               break;
  1613.         case  1 : break;        /* nop */
  1614.  
  1615.               /* we are very liberal on MSS stuff */
  1616.         case  2 : if (*options == 2) {
  1617.                   opt_temp = intel16( *(word*)(&options[1]));
  1618.                   if (opt_temp < s->mss )
  1619.                   s->mss = opt_temp;
  1620.               }
  1621.               numoptions -= 2 + *options;
  1622.               options += *options;
  1623.               break;
  1624.         }
  1625.     }
  1626.     }
  1627.     /* done option processing */
  1628.  
  1629.         len -= x;        /* remove the header length */
  1630.     if ( ldiff >= 0 ) {  /* skip already received bytes */
  1631.     dp += diff;
  1632.     len -= diff;
  1633.  
  1634.     if (s->dataHandler) {
  1635.         s->acknum += s->dataHandler(s, dp, len, ph, tp);  // 94.11.19
  1636. //        s->acknum += s->dataHandler(s, dp, len);
  1637.     } else {
  1638.         /* no handler, just dump to buffer, should be indexed, handles goofs */
  1639.         /* limit receive size to our window */
  1640.         if ( s->rdatalen >= 0 ) {
  1641.                 if ( len > ( x = s->maxrdatalen - s->rdatalen )) {
  1642.             len = x;
  1643.                 }
  1644.         if ( len > 0 ) {
  1645.             s->acknum += len;    /* our new ack begins at end of data */
  1646.                     movmem(dp, s->rdata + s->rdatalen, len );
  1647.             s->rdatalen += len;
  1648. /*
  1649.                                         s->karn_count = 3;
  1650. */
  1651.         }
  1652.         }
  1653.         }
  1654.         s->unhappy = (s->datalen) ? true : false;
  1655.         if (ldiff == 0 && s->unacked && chk_timeout( s->rtt_lasttran )) {
  1656. #ifdef DEBUG
  1657.             if(debug_on >1) printf("data process timeout so set unacked back to 0 from %u\n",s->unacked);
  1658. #endif DEBUG
  1659.             s->unacked = 0;
  1660.         }
  1661.     } else {
  1662.         tcp_sendsoon( s );
  1663.     }
  1664.  
  1665.     s->timeout = set_timeout( tcp_TIMEOUT );
  1666.     return;
  1667. }
  1668.  
  1669. /*
  1670.  * Format and send an outgoing segment
  1671.  */
  1672.  
  1673. static void tcp_send( tcp_Socket *s, int line )
  1674. {
  1675.     tcp_PseudoHeader ph;
  1676.     struct _pkt {
  1677.     in_Header in;
  1678.     tcp_Header tcp;
  1679.     word maxsegopt[2];
  1680.     } *pkt;
  1681.     byte *dp;
  1682.     in_Header *inp;
  1683.     tcp_Header *tcpp;
  1684.     int senddatalen, sendtotlen, sendpktlen, startdata, sendtotdata;
  1685.  
  1686.     int ippkt;         /* 1..s->cwindow */
  1687.  
  1688.     s->recent = 0;
  1689.         pkt = (struct _pkt *)_eth_formatpacket(&s->hisethaddr, /*0x800*/ 8);
  1690.         dp = (byte *) &pkt->maxsegopt;  /* dp constant for multi-packet sends */
  1691.     inp = &pkt->in;
  1692.     tcpp = &pkt->tcp;
  1693.  
  1694. /* this is our total possible send size */
  1695.     if (s->karn_count != 2) {
  1696. #ifdef __SIGNED_BUG__
  1697. /* Morten Terstrup <MorTer@dk-online.dk> found this signed bug. */
  1698.         int size = min (s->datalen, s->window);
  1699.         sendtotdata = size - s->unacked;
  1700.         if (sendtotdata < 0) sendtotdata = 0;
  1701.         startdata = s->unacked;
  1702.     }    else {
  1703.         sendtotdata = min (s->datalen,s->window);
  1704.         startdata = 0;
  1705.     }
  1706. #else
  1707.         /* BUG FIX : jason dent found this */
  1708.      /* sendtotdata = min( s->datalen - s->unacked, s->window );  */
  1709.         sendtotdata = max (min ( s->datalen, s->window ) - s->unacked, 0);
  1710.         startdata = s->unacked;
  1711.     } else {
  1712.         sendtotdata = (s->datalen >= s->window)? s->window : s->datalen;
  1713.         startdata = 0;
  1714.     }
  1715. #endif
  1716.  
  1717. /*
  1718.     if (sendtotdata < 0) sendtotdata = 0;
  1719. */
  1720.     sendtotlen = 0;    /* running count of what we've sent */
  1721.  
  1722.     /* step through our packets */
  1723.     for ( ippkt = 1; ippkt <= s->cwindow; ++ippkt ) {
  1724.         /* adjust size for each packet */
  1725.         senddatalen = min( sendtotdata, s->mss );
  1726.  
  1727.         /*
  1728.                 sendpktlen = senddatalen + sizeof( tcp_Header ) + sizeof( in_Header );
  1729.                 inp->length = intel16( sendpktlen );
  1730.     */
  1731.         /* tcp header */
  1732.         tcpp->srcPort = intel16( s->myport );
  1733.         tcpp->dstPort = intel16( s->hisport );
  1734.         tcpp->seqnum = intel( s->seqnum + startdata ); /* unacked - no longer sendtotlen */
  1735.         tcpp->acknum = intel( s->acknum );
  1736.  
  1737.         tcpp->window = intel16( s->maxrdatalen - s->rdatalen );
  1738.         tcpp->flags = intel16( s->flags | 0x5000 );
  1739.         tcpp->checksum = 0;
  1740.         tcpp->urgentPointer = 0;
  1741.  
  1742.         /* do options if this is our first packet */
  1743.         if ( s->flags & tcp_FlagSYN ) {
  1744.             sendpktlen = sizeof( tcp_Header ) + sizeof( in_Header ) + 4;
  1745.             tcpp->flags = intel16( intel16( tcpp->flags) + 0x1000 );
  1746.             pkt->maxsegopt[0] = 0x0402;
  1747.             pkt->maxsegopt[1] = intel16( s->mss );
  1748.             dp += 4;
  1749.         } else {
  1750.             /* handle packets with data */
  1751.             if (senddatalen > 0) {
  1752.                 sendpktlen = senddatalen + sizeof( tcp_Header ) + sizeof( in_Header );
  1753.  
  1754.                 /* get data from appropriate place */
  1755.                 if (s->queuelen) movmem(s->queue + startdata, dp, senddatalen );
  1756.                 else movmem(s->data + startdata, dp, senddatalen);
  1757. /*                dp[ senddatalen ] = 0; */
  1758.             } else {
  1759.             /* handle no-data, not-first-SYN packets */
  1760.                 sendpktlen = sizeof( tcp_Header ) + sizeof( in_Header );
  1761.             }
  1762.         }
  1763.  
  1764.         /* internet header */
  1765.         memset( inp, 0, sizeof( in_Header ));
  1766.         inp->ver = 4;
  1767.         inp->hdrlen = 5;
  1768.         inp->tos = s->tos;
  1769.         inp->identification = intel16( ++ip_id );   /* was post inc */
  1770. //        inp->frag = 0;
  1771.         inp->ttl = 254;
  1772.         inp->proto = TCP_PROTO;
  1773.         inp->checksum = 0;
  1774.         inp->source = intel( s->myaddr );
  1775.         inp->destination = intel( s->hisaddr );
  1776.         inp->length = intel16( sendpktlen );
  1777.  
  1778.         inp->checksum = ~checksum( inp, sizeof(in_Header));
  1779.  
  1780.         /* compute tcp checksum */
  1781.         ph.src = inp->source;   /* already INTELled */
  1782.         ph.dst = inp->destination;
  1783.         ph.mbz = 0;
  1784.         ph.protocol = 6;
  1785.         ph.length = intel16( sendpktlen - sizeof(in_Header));
  1786. /*
  1787.         ph.checksum = checksum(&pkt->tcp, (sendpktlen - sizeof(in_Header) +1) & 0xfffe);
  1788. */
  1789.         ph.checksum = checksum(&pkt->tcp, sendpktlen - sizeof(in_Header));
  1790.  
  1791.         tcpp->checksum = ~checksum(&ph, sizeof(ph));
  1792.  
  1793.         if (_dbugxmit) (*_dbugxmit)( (sock_type *)s, inp, tcpp, line );
  1794.         if (debug_on > 1) {
  1795.             mono[0]++;
  1796.             colour[0]++;
  1797.             mono[2] = colour[2] = (s->flags & tcp_FlagSYN) ? 'S' : ' ';
  1798.             mono[4] = colour[4] = (s->flags & tcp_FlagACK) ? 'A' : ' ';
  1799.             mono[6] = colour[6] = (s->flags & tcp_FlagFIN) ? 'F' : ' ';
  1800.             mono[8] = colour[8] = (s->flags & tcp_FlagRST) ? 'R' : ' ';
  1801.         }
  1802.         if ( _eth_send( intel16( inp->length ))) { /* encounterred error */
  1803.             tcp_sendsoon( s );
  1804.             return;
  1805.         }
  1806.  
  1807.         /* do next ip pkt */
  1808.         sendtotlen += senddatalen;
  1809.         startdata += senddatalen;
  1810.         sendtotdata -= senddatalen;
  1811.         if (sendtotdata <= 0 ) break;
  1812.     }
  1813.     s->unacked = startdata;
  1814. #ifdef DEBUG
  1815. if (debug_on) printf(" Sent %u/%u bytes in %u/%u packets  with (%u) unacked  SYN %lu  line %u\n",
  1816.         sendtotlen, s->window, (ippkt-1), s->cwindow, s->unacked, s->seqnum, line);
  1817. #endif DEBUG
  1818.     s->vj_last = 0;
  1819.     if ( s->karn_count == 2 ) {
  1820.         if (s->rto) s->rto = (s->rto * 3) / 2;
  1821.         else s->rto = 4;
  1822.     } else {
  1823.         /* vj_last nonzero if we expect an immediate response */
  1824.         if (s->unhappy || s->datalen)
  1825.             s->vj_last = set_ttimeout( 0 );
  1826.     s->karn_count = 0;
  1827.     }
  1828.     s->rtt_time = set_ttimeout( s->rto + 2 );
  1829.     if (sendtotlen > 0 ) s->rtt_lasttran =  s->rtt_time + s->rto;
  1830. }
  1831.  
  1832. /*
  1833.  * Format and send a reset tcp packet
  1834.  */
  1835. static void tcp_rst( in_Header *his_ip, tcp_Header *oldtcpp )
  1836. {
  1837.     tcp_PseudoHeader ph;
  1838.     struct _pkt {
  1839.         in_Header in;
  1840.         tcp_Header tcp;
  1841.     word maxsegopt[2];
  1842.     } *pkt;   /*, *his_pkt; */
  1843.  
  1844.     static longword nextrst = 0L;
  1845.     word oldflags;
  1846.     in_Header *inp;
  1847.     tcp_Header *tcpp;
  1848.     eth_Header *eth;
  1849.     int sendtotlen;    /* length of packet */
  1850.     int temp;
  1851. #ifdef NEVER
  1852.     longword templong;
  1853. #endif
  1854.  
  1855.     /* see RFC 793 page 65 for details */
  1856.  
  1857.     if ( !chk_timeout( nextrst )) return;
  1858.     nextrst = set_ttimeout( 1 );
  1859.  
  1860.     oldflags = intel16( oldtcpp->flags );
  1861.     if (oldflags & tcp_FlagRST ) return;
  1862. #ifdef NEVER
  1863.     if ( (oldflags & (tcp_FlagACK | tcp_FlagFIN)) == (tcp_FlagACK | tcp_FlagFIN) ){
  1864.         templong = oldtcpp->seqnum;
  1865.         oldtcpp->seqnum = oldtcpp->acknum;
  1866.         oldtcpp->acknum = templong;
  1867.         oldflags = tcp_FlagACK;
  1868.     } else if ((oldflags & (tcp_FlagSYN | tcp_FlagACK)) ==  tcp_FlagSYN ) {
  1869.         oldtcpp->acknum = intel( intel( oldtcpp->seqnum ) + 1 );
  1870.         oldtcpp->seqnum = 0;
  1871.         oldflags = tcp_FlagACK | tcp_FlagRST;
  1872.     } else if ( oldflags & tcp_FlagACK ) {
  1873.         oldtcpp->seqnum = oldtcpp->acknum;
  1874.         oldtcpp->acknum = 0;
  1875.     } else {
  1876.         oldtcpp->acknum = intel( intel(oldtcpp->seqnum) + 1);
  1877.         oldtcpp->seqnum = 0;
  1878.     }
  1879.     if ( oldflags & ( tcp_FlagFIN | tcp_FlagSYN ) == 0 )
  1880.         oldflags ^= tcp_FlagACK | tcp_FlagRST;
  1881.  
  1882.     if ( oldflags & tcp_FlagACK ) {
  1883.         oldtcpp->seqnum = oldtcpp->acknum;
  1884.  
  1885. #else
  1886.     /* better strategy - Dean Roth */
  1887.     if ( oldflags & tcp_FlagACK ) {
  1888.         oldtcpp->seqnum = oldtcpp->acknum;
  1889.         oldtcpp->acknum = 0;
  1890.         oldflags = tcp_FlagRST;
  1891.     } else if ((oldflags & (tcp_FlagSYN | tcp_FlagACK)) ==  tcp_FlagSYN ) {
  1892.         oldtcpp->acknum = intel( intel( oldtcpp->seqnum ) + 1 );
  1893.         oldtcpp->seqnum = 0;
  1894.         oldflags = tcp_FlagACK | tcp_FlagRST;
  1895.     } else {
  1896.         temp = intel16( his_ip->length) - in_GetHdrlenBytes( his_ip );
  1897.         oldtcpp->acknum = intel( intel( oldtcpp->seqnum ) + temp );
  1898.         oldtcpp->seqnum = 0;
  1899.         oldflags = tcp_FlagRST;
  1900.     }
  1901. #endif
  1902.  
  1903. /* 94.11.19 -- removed, not used? */
  1904. /*    his_pkt  = (struct _pkt*)( his_ip );  */
  1905.  
  1906.     /* convoluted mechanism - reads his ethernet address or garbage */
  1907.     eth = _eth_hardware( (byte *)his_ip );
  1908.  
  1909.     pkt = (struct _pkt *)_eth_formatpacket( (eth_address *)eth, 8);
  1910.     inp = &pkt->in;
  1911.     tcpp = &pkt->tcp;
  1912.  
  1913.     sendtotlen = sizeof( tcp_Header ) + sizeof( in_Header );
  1914.     memset( inp, 0, sizeof( in_Header ));
  1915.     inp->length = intel16( sendtotlen );
  1916.  
  1917.     /* tcp header */
  1918.     tcpp->srcPort = oldtcpp->dstPort;
  1919.     tcpp->dstPort = oldtcpp->srcPort;
  1920.     tcpp->seqnum = oldtcpp->seqnum;
  1921.     tcpp->acknum = oldtcpp->acknum;
  1922.     tcpp->window = 0;
  1923. /*    tcpp->flags = intel16( oldflags ); */
  1924.     /* BUG FIX : jason dent found this thanks to SCO */
  1925.     tcpp->flags = intel16( (oldflags & 0x0fff ) | 0x5000 );
  1926.     tcpp->checksum = 0;
  1927.     tcpp->urgentPointer = 0;
  1928.  
  1929.     /* internet header */
  1930.     inp->ver = 4;
  1931.     inp->hdrlen = 5;
  1932.     inp->tos = his_ip->tos;
  1933.     inp->identification = intel16( ++ip_id );
  1934. //    inp->frag = 0;
  1935.     inp->ttl = 254;
  1936.     inp->proto = TCP_PROTO;
  1937.     inp->checksum = 0;
  1938.     inp->source = his_ip->destination;
  1939.     inp->destination = his_ip->source;
  1940.  
  1941.     inp->checksum = ~checksum( inp, sizeof(in_Header))/* 0*/;
  1942.  
  1943.     /* compute tcp checksum */
  1944.     ph.src = inp->source;    /* already INTELled */
  1945.     ph.dst = inp->destination;
  1946.     ph.mbz = 0;
  1947.     ph.protocol = 6;
  1948.     ph.length = intel16( sendtotlen - sizeof(in_Header));
  1949.  
  1950.     ph.checksum = checksum(&pkt->tcp, sizeof(tcp_Header));
  1951.     tcpp->checksum =  ~checksum(&ph, sizeof(ph));
  1952.  
  1953.     if (_dbugxmit) (*_dbugxmit)(NULL,inp,tcpp,__LINE__);
  1954.     _eth_send( intel16( inp->length ));
  1955. }
  1956.  
  1957.  
  1958. /**********************************************************************
  1959.  * socket functions
  1960.  **********************************************************************/
  1961.  
  1962. /* socket based stuff */
  1963.  
  1964. /*
  1965.  * sock_read - read a socket with maximum n bytes
  1966.  *         - busywaits until buffer is full but calls s->usr_yield
  1967.  *         - returns count also when connection gets closed
  1968.  */
  1969. int sock_read( sock_type *s, byte *dp, int len )
  1970. {
  1971.     int templen, count;
  1972.     count = 0;
  1973.     do {
  1974.     if ( s->udp.ip_type == UDP_PROTO )
  1975.             templen = udp_read( &(s->udp), dp, len );
  1976.     else
  1977.             templen = tcp_read( &(s->tcp), dp, len);
  1978.         if (s->tcp.usr_yield) (s->tcp.usr_yield)();
  1979.         if (templen < 1 ) {
  1980.             if (!tcp_tick( s )) return( count );
  1981.         } else {
  1982.             count += templen;
  1983.             dp += templen;
  1984.             len -= templen;
  1985.         }
  1986.     } while ( len );
  1987.     return( count );
  1988. }
  1989.  
  1990. /*
  1991.  * sock_fead - read a socket with maximum n bytes
  1992.  *         - does not busywait until buffer is full
  1993.  */
  1994. int sock_fastread( sock_type *s, byte *dp, int len )
  1995. {
  1996.     if ( s->udp.ip_type == UDP_PROTO )
  1997.         len = udp_read( &(s->udp), dp, len );
  1998.     else
  1999.         len = tcp_read( &(s->tcp), dp, len);
  2000.     return( len );
  2001. }
  2002.  
  2003.  
  2004. /*
  2005.  * sock_write - writes data and returns length written
  2006.  *          - does not perform flush
  2007.  *          - repeatedly calls s->usr_yield
  2008.  */
  2009.  
  2010. int sock_write( sock_type *s, byte *dp, int len )
  2011. {
  2012.     int offset, oldlen, oldmode, proto;
  2013.  
  2014.     oldlen = len;
  2015.     offset = 0;
  2016.  
  2017.     proto = (s->udp.ip_type == TCP_PROTO);
  2018.     if ( proto ) oldmode = s->tcp.flags & tcp_FlagPUSH;
  2019.     while ( len  > 0) {
  2020.         if (proto) {
  2021.             s->tcp.flags |= oldmode;
  2022.             offset += tcp_write( &(s->tcp), &dp[ offset ], len);
  2023.         } else
  2024.             offset += udp_write( &(s->udp), &dp[ offset ], len, offset );
  2025.     len = oldlen - offset;
  2026.     if (s->udp.usr_yield)(s->udp.usr_yield)();
  2027.     if (!tcp_tick(s)) return( 0 );
  2028.     }
  2029.     return( oldlen );
  2030. }
  2031.  
  2032.  
  2033. /* NOTE: for UDP, assumes data fits in one datagram, else only the first
  2034.        fragment will be sent!!!!!  Because _mss is used for splits,
  2035.        by default the max data size is 1400 - UDP_LENGTH for a non-fragged
  2036.        datagram.
  2037.  */
  2038. int sock_fastwrite( sock_type *s, byte *dp, int len )
  2039. {
  2040.     return( ( s->udp.ip_type == UDP_PROTO ) ?
  2041.         udp_write( &(s->udp), dp, len, 0 ) :
  2042.         tcp_write( &(s->tcp), dp, len) );
  2043. }
  2044.  
  2045. int sock_setbuf( sock_type *s, byte *dp, int len )
  2046. {
  2047.     if ( len < 0 ) return( 0 );
  2048.     if (len == 0 || dp == NULL ) {
  2049.         s->tcp.rdata = s->tcp.rddata;
  2050.         s->tcp.maxrdatalen = tcp_MaxBufSize;
  2051.     } else {
  2052.         s->tcp.rdata = dp;
  2053.         s->tcp.maxrdatalen = len;
  2054.     }
  2055.     return( s->tcp.maxrdatalen);
  2056. }
  2057.  
  2058. int sock_enqueue( sock_type *s, byte *dp, int len )
  2059. {
  2060.     int written;
  2061.     word offset = 0;
  2062.  
  2063.     if ( len < 0 ) return( 0 );
  2064.     if ( s->udp.ip_type == UDP_PROTO ) {
  2065.         do {
  2066.             written = udp_write( &(s->udp), dp, len, offset );
  2067.             dp += written;
  2068.             offset += written;
  2069.         } while (len -= written > 0);
  2070.     } else {
  2071.         s->tcp.queue = dp;
  2072.         s->tcp.queuelen = len;
  2073.         s->tcp.datalen = len;
  2074.         tcp_send( &(s->tcp), __LINE__ );  /* start sending it */
  2075.     }
  2076.     return( len );
  2077. }
  2078.  
  2079. void sock_noflush( sock_type *s )
  2080. {
  2081.     if ( s->tcp.ip_type == TCP_PROTO ) {
  2082.     s->tcp.flags &= ~tcp_FlagPUSH;
  2083.     s->tcp.sock_mode |= TCP_LOCAL ;
  2084.     }
  2085. }
  2086.  
  2087. void sock_flush( sock_type *s )
  2088. {
  2089.     if ( s->tcp.ip_type == TCP_PROTO ) {
  2090.         s->tcp.sock_mode &= ~TCP_LOCAL;
  2091.     tcp_Flush( &(s->tcp) );
  2092.     }
  2093. }
  2094.  
  2095. /*
  2096.  * sock_flushnext - cause next transmission to have a flush
  2097.  */
  2098. void sock_flushnext( sock_type *s)
  2099. {
  2100.     if (s->tcp.ip_type == TCP_PROTO ) {
  2101.         s->tcp.flags |= tcp_FlagPUSH;
  2102.         s->tcp.sock_mode &= ~TCP_LOCAL;
  2103.     }
  2104. }
  2105.  
  2106. /*
  2107.  * sock_putc - put a character
  2108.  *         - no expansion but flushes on '\n'
  2109.  *         - returns character
  2110.  */
  2111. byte sock_putc( sock_type *s, byte c )
  2112. {
  2113.     if (( c == '\n') || ( c == '\r'))
  2114.     sock_flushnext( s );
  2115.     sock_write( s, &c, 1 );
  2116.     return( c );
  2117. }
  2118.  
  2119. int sock_getc( sock_type *s )
  2120. {
  2121.     char ch;
  2122.     return( sock_read( s, &ch, 1 ) < 1 ? EOF : ch );
  2123. }
  2124.  
  2125. /*
  2126.  * sock_puts - does not append carriage return in binary mode
  2127.  *         - returns length
  2128.  */
  2129. int sock_puts( sock_type *s, byte *dp )
  2130. {
  2131.     int len;   /*, oldmode;*/
  2132.  
  2133.     len = strlen( dp );
  2134.  
  2135.     if (s->tcp.sock_mode & TCP_MODE_ASCII ) {
  2136.         if (s->tcp.ip_type == TCP_PROTO )
  2137.             s->tcp.sock_mode |= TCP_LOCAL;
  2138.         sock_noflush( s );
  2139.         if (len) sock_write( s, dp, len );
  2140.         sock_flushnext( s );
  2141.         sock_write( s, "\r\n", 2 );
  2142.     } else {
  2143.         sock_flushnext( s );
  2144.         sock_write( s, dp, len );
  2145.     }
  2146.     return( len );
  2147. }
  2148.  
  2149. /*
  2150.  * sock_update - update the socket window size to the other guy
  2151.  */
  2152. static void sock_update( tcp_Socket *s )
  2153. {
  2154.     if (s->ip_type == TCP_PROTO) {
  2155.         if ( !s->rdatalen )
  2156.             tcp_send( s, __LINE__ );              /* update the window */
  2157.     else
  2158.         tcp_sendsoon( s );
  2159.     }
  2160. }
  2161.  
  2162. /*
  2163.  * sock_gets - read a string from any socket
  2164.  *         - return length of returned string
  2165.  *           - removes end of line terminator(s)
  2166.  *
  2167.  *           - Quentin Smart fixed some problems
  2168.  */
  2169. int sock_gets( sock_type *s, byte *dp, int n )
  2170. {
  2171.     int len, *np;
  2172.     char *src_p, *temp, *temp2;
  2173.  
  2174.     if ( s->udp.ip_type == UDP_PROTO ) {
  2175.     src_p = s->udp.rdata;
  2176.     np = &s->udp.rdatalen;
  2177.     } else {
  2178.     src_p = s->tcp.rdata;
  2179.     np = &s->tcp.rdatalen;
  2180.     }
  2181.     if ( *np == 0 ) return( 0 );
  2182.  
  2183.     // eat trailing \n or \0 from previous line
  2184.     if ( *src_p == 0 || *src_p == '\n' ) {
  2185.         movmem( src_p + 1, src_p, *np -= 1 );
  2186.         if ( !*np ) return( 0 );
  2187.     }
  2188.  
  2189.     if ( --n > *np ) n = *np;
  2190.  
  2191.     // Q.Smart found and fixed a bug here
  2192.     memcpy( dp, src_p, n );     // copy everything
  2193.     dp[ n ] = 0;                // terminate new string
  2194.     temp = memchr( dp, '\n', n);
  2195.     temp2= memchr( dp, '\r', n);
  2196.  
  2197.     if (temp)  *temp = 0;
  2198.     if (temp2) *temp2= 0;
  2199.  
  2200.     // skip if there were no crs
  2201.     if ( !temp2 ) {
  2202.         *dp = 0;
  2203.         return( 0 );
  2204.     }
  2205.  
  2206. //  not: len = strlen( dp );
  2207.     len = (int)(( temp ? min( FP_OFF(temp), FP_OFF(temp2)) :
  2208.         FP_OFF(temp2)) - FP_OFF(dp));
  2209.  
  2210.     // expect \r\n or \r\0 or \n or \r
  2211.     // so get first of the two
  2212.  
  2213.     if ( temp == NULL ) {       /* handles \r only */
  2214.         temp = temp2;
  2215.         temp2 = NULL;
  2216.     } else if ( FP_OFF( temp ) > FP_OFF( temp2 ))
  2217.         temp = temp2;           // handles trailing \n or \0
  2218.  
  2219.     n = len + 1;                // account for first \r
  2220.  
  2221.     // we check next char if it exists, and skip it if 0, \r, or \n
  2222.     if ((*np > n) && !src_p[n] ) n++;
  2223.     movmem( &src_p[ n ], src_p, *np -= n );
  2224.     if (*np < 0) *np = 0;
  2225.  
  2226.     sock_update( &(s->tcp) );   /* new window */
  2227.     return( len );
  2228. }
  2229.  
  2230.  
  2231. /*
  2232.  * sock_dataready - returns number of bytes waiting to be ready
  2233.  *          - if in ASCII mode, return 0 until a line is present
  2234.  *            or the buffer is full
  2235.  */
  2236. int sock_dataready( sock_type *s )
  2237. {
  2238.     int len;
  2239.     char *p;
  2240.  
  2241.     if (!(len = s->tcp.rdatalen)) return( 0 );
  2242.  
  2243.     if ( s->tcp.sock_mode & TCP_MODE_ASCII ) {
  2244.         p = s->tcp.rdata;
  2245.         if ( *p == '\n' ) {
  2246.             movmem( p + 1, p, s->tcp.rdatalen = --len);
  2247.             if ( ! len ) return( 0 );
  2248.         }
  2249.         /* check for terminating \r */
  2250.         if ( memchr( p, '\r', len))
  2251.             return( len );
  2252.         return( 0 );
  2253.     } else
  2254.         return( len );
  2255. }
  2256.  
  2257. int sock_established( sock_type *s )
  2258. {
  2259.     switch ( s->tcp.ip_type ) {
  2260.     case UDP_PROTO :
  2261.         return( 1 );
  2262.     case TCP_PROTO :
  2263.                 return( s->tcp.state == tcp_StateESTAB ||
  2264.                         s->tcp.state == tcp_StateESTCL ||
  2265.                         s->tcp.state == tcp_StateCLOSWT );
  2266.     default :
  2267.         return( 0 );
  2268.     }
  2269. }
  2270.  
  2271. void sock_close( sock_type *s )
  2272. {
  2273.     switch (s->udp.ip_type) {
  2274.     case UDP_PROTO :
  2275.         udp_close( &(s->udp) );
  2276.         break;
  2277.     case TCP_PROTO :
  2278.         tcp_close( &(s->tcp) );
  2279.         tcp_tick( s );
  2280.         break;
  2281.     }
  2282. }
  2283.  
  2284. void sock_sturdy( sock_type *s, int level )
  2285. {
  2286.     s->tcp.rigid = level;
  2287.     if ( s->tcp.rigid < s->tcp.stress ) sock_abort( s );
  2288. }
  2289.  
  2290. /*
  2291.  * _ip_delay0 called by macro sock_wait_established()
  2292.  * _ip_delay1 called by macro sock_wait_intput()
  2293.  * _ip_delay2 called by macro sock_wait_closed();
  2294.  *
  2295.  */
  2296.  
  2297. int _ip_delay0( sock_type *s, int timeoutseconds, sockfunct_t fn, int *statusptr )
  2298. {
  2299.     int status;
  2300.     ip_timer_init( s , timeoutseconds );
  2301.     do {
  2302.     if ( s->tcp.ip_type == TCP_PROTO ) {
  2303.         if ( tcp_established( &(s->tcp) )) {
  2304.         status = 0;
  2305.         break;
  2306.         }
  2307.     }
  2308.     kbhit();    /* permit ^c */
  2309.     if ( !tcp_tick( s )) {
  2310.              if (!s->tcp.err_msg) s->tcp.err_msg = "Host refused connection";
  2311.          status = -1;    /* get an early reset */
  2312.          break;
  2313.     }
  2314.     if ( ip_timer_expired( s )) {
  2315.             s->tcp.err_msg = "Open timed out";
  2316.             sock_close( s );
  2317.         status = -1;
  2318.         break;
  2319.     }
  2320.     if ( (fn != NULL) && ((status = fn(s)) != 0) ) break;
  2321.     if ( s->tcp.usr_yield ) (*s->tcp.usr_yield)();
  2322.     if ( s->tcp.ip_type == UDP_PROTO ) {
  2323.         status = 0;
  2324.         break;
  2325.     }
  2326.     } while ( 1 );
  2327.     if (statusptr) *statusptr = status;
  2328.     return( status );
  2329. }
  2330.  
  2331. int _ip_delay1( sock_type *s, int timeoutseconds, sockfunct_t fn, int *statusptr)
  2332. {
  2333.     int status;
  2334.     ip_timer_init( s , timeoutseconds );
  2335.  
  2336.     sock_flush( s );    /* new enhancement */
  2337.  
  2338.     do {
  2339.     if ( sock_dataready( s )) {
  2340.         status = 0;
  2341.         break;
  2342.     }
  2343.     kbhit();    /* permit ^c */
  2344.  
  2345.     if ( !tcp_tick( s )) {
  2346.         status = 1;
  2347.         break;
  2348.     }
  2349.     if ( ip_timer_expired( s )) {
  2350.             s->tcp.err_msg = "Connection timed out";
  2351.             sock_close( s );
  2352.         status = -1;
  2353.         break;
  2354.     }
  2355.     if (fn) {
  2356.         if ((status = fn(s)) != 0)
  2357.         break;
  2358.     }
  2359.     if ( s->tcp.usr_yield ) (*s->tcp.usr_yield)();
  2360.     } while ( 1 );
  2361.     if (statusptr) *statusptr = status;
  2362.     return( status );
  2363. }
  2364.  
  2365. int _ip_delay2( sock_type *s, int timeoutseconds, sockfunct_t fn, int *statusptr)
  2366. {
  2367.     int status;
  2368.     ip_timer_init( s , timeoutseconds );
  2369.  
  2370.     if (s->tcp.ip_type != TCP_PROTO ) {
  2371.         if ( statusptr ) * statusptr = 1;
  2372.         return( 1 );
  2373.     }
  2374.  
  2375.     do {
  2376.         /* in this situation we KNOW user not planning to read rdata */
  2377.         s->tcp.rdatalen = 0;
  2378.     kbhit();    /* permit ^c */
  2379.     if ( !tcp_tick( s )) {
  2380.         status = 1;
  2381.         break;
  2382.     }
  2383.     if ( ip_timer_expired( s )) {
  2384.             s->tcp.err_msg = "Connection timed out";
  2385.         sock_abort( s );
  2386.         status = -1;
  2387.         break;
  2388.     }
  2389.     if (fn) {
  2390.         if ((status = fn(s)) != 0)
  2391.         break;
  2392.     }
  2393.     if ( s->tcp.usr_yield ) (*s->tcp.usr_yield)();
  2394.  
  2395.     } while ( 1 );
  2396.     if (statusptr) *statusptr = status;
  2397.     return( status );
  2398. }
  2399.  
  2400. char *rip( char *s )
  2401. {
  2402.     char *temp;
  2403.  
  2404.     if ((temp = strchr( s, '\n')) != NULL) *temp = '\0';
  2405.     if ((temp = strchr( s, '\r')) != NULL) *temp = '\0';
  2406.     return( s );
  2407. }
  2408.