// tcp_watchdog.cpp
// Copyright (C) 2006 - 2009 MicroNeil Research Corporation
// See tcp_watchdog.hpp for details.

#include "tcp_watchdog.hpp"

const ThreadType TCPWatchdog::Type("TCPWatchdog");                              // Thread type.

const ThreadState TCPWatchdog::Watching("Watching");                            // State when waiting to fire.
const ThreadState TCPWatchdog::KilledSocket("KilledSocket");                    // Killed The Socket.
const ThreadState TCPWatchdog::LiveAndLetBe("LiveAndLetBe");                    // Shutdown without incident.

TCPWatchdog::TCPWatchdog(Socket& SocketToWatch, int Milliseconds) :             // Construct with
  MySocket(SocketToWatch),                                                      // a socket to watch,
  MyTimeout(Milliseconds),                                                      // a time limit,
  StillAlive(true) {                                                            // and a true alive flag.
      run();                                                                    // Run the thread.
}

TCPWatchdog::~TCPWatchdog() {                                                   // When we go away, we
    stop();                                                                     // need to stop.
}

void TCPWatchdog::reset() {                                                     // We can be reset by
    MyTimeout.restart();                                                        // restarting the timeout.
}

void TCPWatchdog::reset(int Milliseconds) {                                     // We can also be reset by
    MyTimeout.setDuration(Milliseconds);                                        // setting a new timeout and
    MyTimeout.restart();                                                        // starting fresh.
}

void TCPWatchdog::stop() {                                                      // If we are stopped then
    MyTimeout.restart();                                                        // we restart the timeout for safety,
    if(StillAlive) {                                                            // IF we're alive when we get here
        CurrentThreadState(LiveAndLetBe);                                       // we are "calling off the dog".
    }
    StillAlive = false;                                                         // falsify our alive flag, and
    join();                                                                     // wait for our thread to end.
}

void TCPWatchdog::myTask() {                                                    // This is the job we do.
    const int OneSecond = 1000;                                                 // One second in milliseconds.
    Sleeper WaitATic(OneSecond);                                                // Set up a one second sleeper.
    while(StillAlive) {                                                         // While we are alive,
        CurrentThreadState(Watching);                                           // we are watching the clock.
        WaitATic();                                                             // Every second or so we will
        if(MyTimeout.isExpired()) {                                             // check to see if we've expired.
            CurrentThreadState(KilledSocket);                                   // If the clock expires - we kill!
            StillAlive = false;                                                 // To do that, we turn ourselves
            MySocket.close();                                                   // off and close the socket.
        }
    }
}
