home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / net / inet / timer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-01  |  6.8 KB  |  238 lines

  1. /*
  2.  * INET        An implementation of the TCP/IP protocol suite for the LINUX
  3.  *        operating system.  INET is implemented using the  BSD Socket
  4.  *        interface as the means of communication with the user level.
  5.  *
  6.  *        TIMER - implementation of software timers.
  7.  *
  8.  * Version:    @(#)timer.c    1.0.7    05/25/93
  9.  *
  10.  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  11.  *        Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  12.  *        Corey Minyard <wf-rch!minyard@relay.EU.net>
  13.  *        Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de>
  14.  *        Florian La Roche, <flla@stud.uni-sb.de>
  15.  *
  16.  * Fixes:
  17.  *        Alan Cox    :    To avoid destroying a wait queue as we use it
  18.  *                    we defer destruction until the destroy timer goes
  19.  *                    off.
  20.  *        Alan Cox    :    Destroy socket doesnt write a status value to the
  21.  *                    socket buffer _AFTER_ freeing it! Also sock ensures
  22.  *                    the socket will get removed BEFORE this is called
  23.  *                    otherwise if the timer TIME_DESTROY occurs inside
  24.  *                    of inet_bh() with this socket being handled it goes
  25.  *                    BOOM! Have to stop timer going off if inet_bh is
  26.  *                    active or the destroy causes crashes.
  27.  *
  28.  *        This program is free software; you can redistribute it and/or
  29.  *        modify it under the terms of the GNU General Public License
  30.  *        as published by the Free Software Foundation; either version
  31.  *        2 of the License, or (at your option) any later version.
  32.  */
  33.  
  34. #include <linux/types.h>
  35. #include <linux/errno.h>
  36. #include <linux/socket.h>
  37. #include <linux/in.h>
  38. #include <linux/kernel.h>
  39. #include <linux/sched.h>
  40. #include <linux/timer.h>
  41. #include <asm/system.h>
  42. #include <linux/interrupt.h>
  43. #include "inet.h"
  44. #include "dev.h"
  45. #include "ip.h"
  46. #include "protocol.h"
  47. #include "tcp.h"
  48. #include "skbuff.h"
  49. #include "sock.h"
  50. #include "arp.h"
  51.  
  52. void
  53. delete_timer (struct sock *t)
  54. {
  55.   unsigned long flags;
  56.  
  57.   save_flags (flags);
  58.   cli();
  59.  
  60.   t->timeout = 0;
  61.   del_timer (&t->timer);
  62.  
  63.   restore_flags (flags);
  64. }
  65.  
  66. void
  67. reset_timer (struct sock *t, int timeout, unsigned long len)
  68. {
  69.   delete_timer (t);
  70.  
  71.   if (timeout != -1)
  72.     t->timeout = timeout;
  73.  
  74. #if 1
  75.   /* FIXME: ??? */
  76.   if ((int) len < 0)    /* prevent close to infinite timers. THEY _DO_ */
  77.     len = 3;    /* happen (negative values ?) - don't ask me why ! -FB */
  78. #endif
  79.   t->timer.expires = len;
  80.   add_timer (&t->timer);
  81. }
  82.  
  83.  
  84. /*
  85.  * Now we will only be called whenever we need to do
  86.  * something, but we must be sure to process all of the
  87.  * sockets that need it.
  88.  */
  89. void
  90. net_timer (unsigned long data)
  91. {
  92.   struct sock *sk = (struct sock*)data;
  93.   int why = sk->timeout;
  94.   /* timeout is overwritten by 'delete_timer' and 'reset_timer' */
  95.  
  96.   if (sk->inuse || in_inet_bh()) {
  97.     sk->timer.expires = 10;
  98.     add_timer(&sk->timer);
  99.     return;
  100.   }
  101.   sk->inuse = 1;
  102.  
  103.   DPRINTF ((DBG_TMR, "net_timer: found sk=%X why = %d\n", sk, why));
  104.   if (sk->wfront && 
  105.       before(sk->window_seq, sk->wfront->h.seq) &&
  106.       sk->send_head == NULL &&
  107.       sk->ack_backlog == 0 &&
  108.       sk->state != TCP_TIME_WAIT)
  109.     reset_timer(sk, TIME_PROBE0, sk->rto);
  110.   else if (sk->keepopen)
  111.     reset_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
  112.  
  113.   /* Always see if we need to send an ack. */
  114.   if (sk->ack_backlog) {
  115.     sk->prot->read_wakeup (sk);
  116.     if (! sk->dead)
  117.       wake_up_interruptible (sk->sleep);
  118.   }
  119.  
  120.   /* Now we need to figure out why the socket was on the timer. */
  121.   switch (why) {
  122.     case TIME_DONE:
  123.     if (! sk->dead || sk->state != TCP_CLOSE) {
  124.       printk ("non dead socket in time_done\n");
  125.       release_sock (sk);
  126.       break;
  127.     }
  128.     destroy_sock (sk);
  129.     break;
  130.     case TIME_DESTROY:
  131.     /* We've waited for a while for all the memory associated with
  132.      * the socket to be freed.  We need to print an error message.
  133.      */
  134.     if(sk->wmem_alloc!=0 || sk->rmem_alloc!=0)
  135.     {
  136.         DPRINTF ((DBG_TMR, "possible memory leak.  sk = %X\n", sk));
  137.         sk->wmem_alloc++;    /* So it DOESNT go away */
  138.         destroy_sock (sk);
  139.         sk->wmem_alloc--;    /* Might now have hit 0 - fall through and do it again if so */
  140.         sk->inuse = 0;    /* This will be ok, the destroy won't totally work */
  141.     }
  142.     if(sk->wmem_alloc==0 && sk->rmem_alloc==0)
  143.         destroy_sock(sk);    /* Socket gone, DONT update sk->inuse! */
  144.     break;
  145.     case TIME_CLOSE:
  146.     /* We've waited long enough, close the socket. */
  147.     sk->state = TCP_CLOSE;
  148.     delete_timer (sk);
  149.     /* Kill the ARP entry in case the hardware has changed. */
  150.     arp_destroy_maybe (sk->daddr);
  151.     if (!sk->dead)
  152.       wake_up_interruptible (sk->sleep);
  153.     sk->shutdown = SHUTDOWN_MASK;
  154.     reset_timer (sk, TIME_DESTROY, TCP_DONE_TIME);
  155.     release_sock (sk);
  156.     break;
  157.     case TIME_PROBE0:
  158.     tcp_send_probe0(sk);
  159.     release_sock (sk);
  160.     break;
  161.     case TIME_WRITE:    /* try to retransmit. */
  162.     /* It could be we got here because we needed to send an ack.
  163.      * So we need to check for that.
  164.      */
  165.     if (sk->send_head) {
  166.       if (jiffies < (sk->send_head->when + sk->rto)) {
  167.         reset_timer (sk, TIME_WRITE, 
  168.              (sk->send_head->when + sk->rto - jiffies));
  169.         release_sock (sk);
  170.         break;
  171.       }
  172.       /* printk("timer: seq %d retrans %d out %d cong %d\n", sk->send_head->h.seq,
  173.          sk->retransmits, sk->packets_out, sk->cong_window); */
  174.       DPRINTF ((DBG_TMR, "retransmitting.\n"));
  175.       sk->prot->retransmit (sk, 0);
  176.       if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
  177.         || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) {
  178.         DPRINTF ((DBG_TMR, "timer.c TIME_WRITE time-out 1\n"));
  179.         arp_destroy_maybe (sk->daddr);
  180.         ip_route_check (sk->daddr);
  181.       }
  182.       if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) {
  183.         DPRINTF ((DBG_TMR, "timer.c TIME_WRITE time-out 2\n"));
  184.         sk->err = ETIMEDOUT;
  185.         if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2
  186.           || sk->state == TCP_LAST_ACK) {
  187.           sk->state = TCP_TIME_WAIT;
  188.           reset_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
  189.         } else {
  190.           sk->prot->close (sk, 1);
  191.           break;
  192.         }
  193.       }
  194.     }
  195.     release_sock (sk);
  196.     break;
  197.     case TIME_KEEPOPEN:
  198.     /* Send something to keep the connection open. */
  199.     if (sk->prot->write_wakeup)
  200.       sk->prot->write_wakeup (sk);
  201.     sk->retransmits++;
  202.     if (sk->shutdown == SHUTDOWN_MASK) {
  203.       sk->prot->close (sk, 1);
  204.       sk->state = TCP_CLOSE;
  205.     }
  206.  
  207.     if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
  208.       || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) {
  209.       DPRINTF ((DBG_TMR, "timer.c TIME_KEEPOPEN time-out 1\n"));
  210.       arp_destroy_maybe (sk->daddr);
  211.       ip_route_check (sk->daddr);
  212.       release_sock (sk);
  213.       break;
  214.     }
  215.     if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) {
  216.       DPRINTF ((DBG_TMR, "timer.c TIME_KEEPOPEN time-out 2\n"));
  217.       arp_destroy_maybe (sk->daddr);
  218.       sk->err = ETIMEDOUT;
  219.       if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2) {
  220.         sk->state = TCP_TIME_WAIT;
  221.         if (!sk->dead)
  222.           wake_up_interruptible (sk->sleep);
  223.         release_sock (sk);
  224.       } else {
  225.         sk->prot->close (sk, 1);
  226.       }
  227.       break;
  228.     }
  229.     release_sock (sk);
  230.     break;
  231.     default:
  232.     printk ("net timer expired - reason unknown, sk=%08X\n", (int)sk);
  233.     release_sock (sk);
  234.     break;
  235.   }
  236. }
  237.  
  238.