home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / WATTCP / WATTCP.ZIP / SRC / PCTCP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-11  |  62.8 KB  |  2,224 lines

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