linux-bk/net/x25/x25_timer.c
<<
>>
Prefs
   1/*
   2 *      X.25 Packet Layer release 002
   3 *
   4 *      This is ALPHA test software. This code may break your machine,
   5 *      randomly fail to work with new releases, misbehave and/or generally
   6 *      screw up. It might even work. 
   7 *
   8 *      This code REQUIRES 2.1.15 or higher
   9 *
  10 *      This module:
  11 *              This module is free software; you can redistribute it and/or
  12 *              modify it under the terms of the GNU General Public License
  13 *              as published by the Free Software Foundation; either version
  14 *              2 of the License, or (at your option) any later version.
  15 *
  16 *      History
  17 *      X.25 001        Jonathan Naylor Started coding.
  18 *      X.25 002        Jonathan Naylor New timer architecture.
  19 *                                      Centralised disconnection processing.
  20 */
  21
  22#include <linux/errno.h>
  23#include <linux/jiffies.h>
  24#include <linux/timer.h>
  25#include <net/sock.h>
  26#include <net/tcp.h>
  27#include <net/x25.h>
  28
  29static void x25_heartbeat_expiry(unsigned long);
  30static void x25_timer_expiry(unsigned long);
  31
  32void x25_init_timers(struct sock *sk)
  33{
  34        struct x25_opt *x25 = x25_sk(sk);
  35
  36        init_timer(&x25->timer);
  37        x25->timer.data     = (unsigned long)sk;
  38        x25->timer.function = &x25_timer_expiry;
  39
  40        /* initialized by sock_init_data */
  41        sk->sk_timer.data     = (unsigned long)sk;
  42        sk->sk_timer.function = &x25_heartbeat_expiry;
  43}
  44
  45void x25_start_heartbeat(struct sock *sk)
  46{
  47        mod_timer(&sk->sk_timer, jiffies + 5 * HZ);
  48}
  49
  50void x25_stop_heartbeat(struct sock *sk)
  51{
  52        del_timer(&sk->sk_timer);
  53}
  54
  55void x25_start_t2timer(struct sock *sk)
  56{
  57        struct x25_opt *x25 = x25_sk(sk);
  58
  59        mod_timer(&x25->timer, jiffies + x25->t2);
  60}
  61
  62void x25_start_t21timer(struct sock *sk)
  63{
  64        struct x25_opt *x25 = x25_sk(sk);
  65
  66        mod_timer(&x25->timer, jiffies + x25->t21);
  67}
  68
  69void x25_start_t22timer(struct sock *sk)
  70{
  71        struct x25_opt *x25 = x25_sk(sk);
  72
  73        mod_timer(&x25->timer, jiffies + x25->t22);
  74}
  75
  76void x25_start_t23timer(struct sock *sk)
  77{
  78        struct x25_opt *x25 = x25_sk(sk);
  79
  80        mod_timer(&x25->timer, jiffies + x25->t23);
  81}
  82
  83void x25_stop_timer(struct sock *sk)
  84{
  85        del_timer(&x25_sk(sk)->timer);
  86}
  87
  88unsigned long x25_display_timer(struct sock *sk)
  89{
  90        struct x25_opt *x25 = x25_sk(sk);
  91
  92        if (!timer_pending(&x25->timer))
  93                return 0;
  94
  95        return x25->timer.expires - jiffies;
  96}
  97
  98static void x25_heartbeat_expiry(unsigned long param)
  99{
 100        struct sock *sk = (struct sock *)param;
 101
 102        bh_lock_sock(sk);
 103        if (sock_owned_by_user(sk)) /* can currently only occur in state 3 */ 
 104                goto restart_heartbeat;
 105
 106        switch (x25_sk(sk)->state) {
 107
 108                case X25_STATE_0:
 109                        /*
 110                         * Magic here: If we listen() and a new link dies
 111                         * before it is accepted() it isn't 'dead' so doesn't
 112                         * get removed.
 113                         */
 114                        if (sock_flag(sk, SOCK_DESTROY) ||
 115                            (sk->sk_state == TCP_LISTEN &&
 116                             sock_flag(sk, SOCK_DEAD))) {
 117                                x25_destroy_socket(sk);
 118                                goto unlock;
 119                        }
 120                        break;
 121
 122                case X25_STATE_3:
 123                        /*
 124                         * Check for the state of the receive buffer.
 125                         */
 126                        x25_check_rbuf(sk);
 127                        break;
 128        }
 129restart_heartbeat:
 130        x25_start_heartbeat(sk);
 131unlock:
 132        bh_unlock_sock(sk);
 133}
 134
 135/*
 136 *      Timer has expired, it may have been T2, T21, T22, or T23. We can tell
 137 *      by the state machine state.
 138 */
 139static inline void x25_do_timer_expiry(struct sock * sk)
 140{
 141        struct x25_opt *x25 = x25_sk(sk);
 142
 143        switch (x25->state) {
 144
 145                case X25_STATE_3:       /* T2 */
 146                        if (x25->condition & X25_COND_ACK_PENDING) {
 147                                x25->condition &= ~X25_COND_ACK_PENDING;
 148                                x25_enquiry_response(sk);
 149                        }
 150                        break;
 151
 152                case X25_STATE_1:       /* T21 */
 153                case X25_STATE_4:       /* T22 */
 154                        x25_write_internal(sk, X25_CLEAR_REQUEST);
 155                        x25->state = X25_STATE_2;
 156                        x25_start_t23timer(sk);
 157                        break;
 158
 159                case X25_STATE_2:       /* T23 */
 160                        x25_disconnect(sk, ETIMEDOUT, 0, 0);
 161                        break;
 162        }
 163}
 164
 165static void x25_timer_expiry(unsigned long param)
 166{
 167        struct sock *sk = (struct sock *)param;
 168
 169        bh_lock_sock(sk);
 170        if (sock_owned_by_user(sk)) { /* can currently only occur in state 3 */
 171                if (x25_sk(sk)->state == X25_STATE_3)
 172                        x25_start_t2timer(sk);
 173        } else
 174                x25_do_timer_expiry(sk);
 175        bh_unlock_sock(sk);
 176}
 177
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.