home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / net / inet / timer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-07  |  6.6 KB  |  265 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 for IP.
  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 doesn't 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 net_bh is
  26.  *                    active or the destroy causes crashes.
  27.  *        Alan Cox    :    Cleaned up unused code.
  28.  *
  29.  *        This program is free software; you can redistribute it and/or
  30.  *        modify it under the terms of the GNU General Public License
  31.  *        as published by the Free Software Foundation; either version
  32.  *        2 of the License, or (at your option) any later version.
  33.  */
  34.  
  35. #include <linux/types.h>
  36. #include <linux/errno.h>
  37. #include <linux/socket.h>
  38. #include <linux/in.h>
  39. #include <linux/kernel.h>
  40. #include <linux/sched.h>
  41. #include <linux/timer.h>
  42. #include <asm/system.h>
  43. #include <linux/interrupt.h>
  44. #include <linux/inet.h>
  45. #include <linux/netdevice.h>
  46. #include "ip.h"
  47. #include "protocol.h"
  48. #include "tcp.h"
  49. #include <linux/skbuff.h>
  50. #include "sock.h"
  51. #include "arp.h"
  52.  
  53. void 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 reset_timer (struct sock *t, int timeout, unsigned long len)
  67. {
  68.     delete_timer (t);
  69.     t->timeout = timeout;
  70. #if 1
  71.   /* FIXME: ??? */
  72.     if ((int) len < 0)    /* prevent close to infinite timers. THEY _DO_ */
  73.         len = 3;    /* happen (negative values ?) - don't ask me why ! -FB */
  74. #endif
  75.     t->timer.expires = len;
  76.     add_timer (&t->timer);
  77. }
  78.  
  79.  
  80. /*
  81.  *    Now we will only be called whenever we need to do
  82.  *    something, but we must be sure to process all of the
  83.  *    sockets that need it.
  84.  */
  85.  
  86. void net_timer (unsigned long data)
  87. {
  88.     struct sock *sk = (struct sock*)data;
  89.     int why = sk->timeout;
  90.  
  91.     /* 
  92.      * only process if socket is not in use
  93.      */
  94.  
  95.     cli();
  96.     if (sk->inuse || in_bh) 
  97.     {
  98.         sk->timer.expires = 10;
  99.         add_timer(&sk->timer);
  100.         sti();
  101.         return;
  102.     }
  103.  
  104.     sk->inuse = 1;
  105.     sti();
  106.  
  107.     /* Always see if we need to send an ack. */
  108.  
  109.     if (sk->ack_backlog && !sk->zapped) 
  110.     {
  111.         sk->prot->read_wakeup (sk);
  112.         if (! sk->dead)
  113.         sk->data_ready(sk,0);
  114.     }
  115.  
  116.     /* Now we need to figure out why the socket was on the timer. */
  117.  
  118.     switch (why) 
  119.     {
  120.         case TIME_DONE:
  121.             if (! sk->dead || sk->state != TCP_CLOSE) 
  122.             {
  123.                 printk ("non dead socket in time_done\n");
  124.                 release_sock (sk);
  125.                 break;
  126.             }
  127.             destroy_sock (sk);
  128.             break;
  129.  
  130.         case TIME_DESTROY:
  131.         /*
  132.          *    We've waited for a while for all the memory associated with
  133.          *    the socket to be freed.
  134.          */
  135.             if(sk->wmem_alloc!=0 || sk->rmem_alloc!=0)
  136.             {
  137.                 sk->wmem_alloc++;    /* So it DOESN'T 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, DON'T 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 (sk->daddr, 0);
  151.             if (!sk->dead)
  152.                 sk->state_change(sk);
  153.             sk->shutdown = SHUTDOWN_MASK;
  154.             reset_timer (sk, TIME_DESTROY, TCP_DONE_TIME);
  155.             release_sock (sk);
  156.             break;
  157. #if 0
  158.         case TIME_PROBE0:
  159.             tcp_send_probe0(sk);
  160.             release_sock (sk);
  161.             break;
  162.         case TIME_WRITE:    /* try to retransmit. */
  163.             /* It could be we got here because we needed to send an ack.
  164.              * So we need to check for that.
  165.              */
  166.         {
  167.             struct sk_buff *skb;
  168.             unsigned long flags;
  169.  
  170.             save_flags(flags);
  171.             cli();
  172.             skb = sk->send_head;
  173.             if (!skb) 
  174.             {
  175.                 restore_flags(flags);
  176.             } 
  177.             else 
  178.             {
  179.                 if (jiffies < skb->when + sk->rto) 
  180.                 {
  181.                     reset_timer (sk, TIME_WRITE, skb->when + sk->rto - jiffies);
  182.                     restore_flags(flags);
  183.                     release_sock (sk);
  184.                     break;
  185.                 }
  186.                 restore_flags(flags);
  187.                 /* printk("timer: seq %d retrans %d out %d cong %d\n", sk->send_head->h.seq,
  188.                     sk->retransmits, sk->packets_out, sk->cong_window); */
  189.                 sk->prot->retransmit (sk, 0);
  190.                 if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
  191.                     || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) 
  192.                 {
  193.                     arp_destroy (sk->daddr, 0);
  194.                     ip_route_check (sk->daddr);
  195.                 }
  196.                 if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) 
  197.                 {
  198.                     sk->err = ETIMEDOUT;
  199.                     if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2 || sk->state == TCP_CLOSING) 
  200.                     {
  201.                         sk->state = TCP_TIME_WAIT;
  202.                         reset_timer (sk, TIME_CLOSE, TCP_TIMEWAIT_LEN);
  203.                     }
  204.                     else
  205.                     {
  206.                         sk->prot->close (sk, 1);
  207.                             break;
  208.                     }
  209.                 }
  210.             }
  211.             release_sock (sk);
  212.             break;
  213.         }
  214.         case TIME_KEEPOPEN:
  215.             /* 
  216.              * this reset_timer() call is a hack, this is not
  217.              * how KEEPOPEN is supposed to work.
  218.              */
  219.             reset_timer (sk, TIME_KEEPOPEN, TCP_TIMEOUT_LEN);
  220.  
  221.             /* Send something to keep the connection open. */
  222.             if (sk->prot->write_wakeup)
  223.                   sk->prot->write_wakeup (sk);
  224.             sk->retransmits++;
  225.             if (sk->shutdown == SHUTDOWN_MASK) 
  226.             {
  227.                 sk->prot->close (sk, 1);
  228.                 sk->state = TCP_CLOSE;
  229.             }
  230.             if ((sk->state == TCP_ESTABLISHED && sk->retransmits && !(sk->retransmits & 7))
  231.                 || (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR1)) 
  232.             {
  233.                 arp_destroy (sk->daddr, 0);
  234.                 ip_route_check (sk->daddr);
  235.                 release_sock (sk);
  236.                 break;
  237.             }
  238.             if (sk->state != TCP_ESTABLISHED && sk->retransmits > TCP_RETR2) 
  239.             {
  240.                 arp_destroy (sk->daddr, 0);
  241.                 sk->err = ETIMEDOUT;
  242.                 if (sk->state == TCP_FIN_WAIT1 || sk->state == TCP_FIN_WAIT2) 
  243.                 {
  244.                     sk->state = TCP_TIME_WAIT;
  245.                     if (!sk->dead)
  246.                         sk->state_change(sk);
  247.                     release_sock (sk);
  248.                   } 
  249.                   else 
  250.                   {
  251.                     sk->prot->close (sk, 1);
  252.                   }
  253.                   break;
  254.             }
  255.             release_sock (sk);
  256.             break;
  257. #endif
  258.         default:
  259.             printk ("net_timer: timer expired - reason %d is unknown\n", why);
  260.             release_sock (sk);
  261.             break;
  262.     }
  263. }
  264.  
  265.