UPMT-master/java/upmt/src/org/zoolu/net/UdpKeepAlive.java
/*
 * Copyright (C) 2006 Luca Veltri - University of Parma - Italy
 * 
 * This source code is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This source code is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this source code; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * Author(s):
 * Luca Veltri (luca.veltri@unipr.it)
 */

package org.zoolu.net;




/** UdpKeepAlive keeps up the connection toward a target node
  * (e.g. toward the seriving proxy, gateway, or remote UAS).
  * It periodically sends keep-alive tokens in order to refresh NAT timeouts
  * (for the UDP session).
  * <p/>
  * It can be used for both signaling (SIP) or data plane (RTP/UDP). 
  */
public class UdpKeepAlive extends Thread
{
   /** Default udp keep-alive token */
   public static final byte[] DEFAULT_TOKEN={ (byte)'\r',(byte)'\n' };
   
   /** Destination socket address */
   protected SocketAddress target;

   /** Time between two keep-alive tokens [millisecs] */
   protected long delta_time;

   /** UdpSocket */
   protected UdpSocket udp_socket;

   /** Udp token packet */
   protected UdpPacket udp_token=null;

   /** Expiration date [millisecs] */
   protected long expire=0; 

   /** Whether it is running */
   protected boolean stop=false;


   /** Creates a new UdpKeepAlive daemon */
   protected UdpKeepAlive(SocketAddress target, long delta_time)
   {  this.target=target;
      this.delta_time=delta_time;
   }


   /** Creates a new UdpKeepAlive daemon */
   public UdpKeepAlive(UdpSocket udp_socket, SocketAddress target, long delta_time)
   {  this.target=target;
      this.delta_time=delta_time;
      init(udp_socket,null);
      start();
   }


   /** Creates a new UdpKeepAlive daemon */
   public UdpKeepAlive(UdpSocket udp_socket, SocketAddress target, UdpPacket udp_token, long delta_time)
   {  this.target=target;
      this.delta_time=delta_time;
      init(udp_socket,udp_token);
      start();
   }


   /** Inits the UdpKeepAlive */
   private void init(UdpSocket udp_socket, UdpPacket udp_packet)
   {  this.udp_socket=udp_socket;
      if (udp_token==null)
      {  byte[] buff=DEFAULT_TOKEN;
         udp_token=new UdpPacket(buff,0,buff.length);
      }
      if (target!=null)
      {  udp_token.setIpAddress(target.getAddress());
         udp_token.setPort(target.getPort());
      }
      this.udp_token=udp_token;
   }


   /** Whether the UDP relay is running */
   public boolean isRunning()
   {  return !stop;
   }

   /** Sets the time (in milliseconds) between two keep-alive tokens */
   public void setDeltaTime(long delta_time)
   {  this.delta_time=delta_time;
   }

   /** Gets the time (in milliseconds) between two keep-alive tokens */
   public long getDeltaTime()
   {  return delta_time;
   }


   /** Sets the destination SocketAddress */
   public void setDestSoAddress(SocketAddress soaddr)
   {  target=soaddr;
      if (udp_token!=null && target!=null)
      {  udp_token.setIpAddress(target.getAddress());
         udp_token.setPort(target.getPort());
      }
         
   }

   /** Gets the destination SocketAddress */
   public SocketAddress getDestSoAddress()
   {  return target;
   }


   /** Sets the expiration time (in milliseconds) */
   public void setExpirationTime(long time)
   {  if (time==0) expire=0;
      else expire=System.currentTimeMillis()+time;
   }


   /** Stops sending keep-alive tokens */
   public void halt()
   {  stop=true;
   }


   /** Sends the kepp-alive packet now. */
   public void sendToken() throws java.io.IOException
   {  // do send?
      if (!stop && target!=null && udp_socket!=null)
      {  udp_socket.send(udp_token);
      }
   }


   /** Main thread. */
   public void run()
   {  try   
      {  while(!stop)
         {  sendToken();
            Thread.sleep(delta_time);
            if (expire>0 && System.currentTimeMillis()>expire) halt(); 
         }
      }
      catch (Exception e) { e.printStackTrace(); }
      udp_socket=null;
   }
   
       
   /** Gets a String representation of the Object */
   public String toString()
   {  String str=null;
      if (udp_socket!=null)
      {  str="udp:"+udp_socket.getLocalAddress()+":"+udp_socket.getLocalPort()+"-->"+target.toString();
      }
      return str+" ("+delta_time+"ms)"; 
   }
    
}
