/*
* TurnServer, the OpenSource Java Solution for TURN protocol. Maintained by the
* Jitsi community (http://jitsi.org).
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.turnserver.stack;
import org.ice4j.*;
/**
* This class is an implementation of Permissions in TURN protocol.
*
* @author Aakash Garg
*
*/
public class Permission
{
/**
* The maximum lifetime allowed for a Permission.
*/
public static final long MAX_LIFETIME = 300 * 1000;
/**
* The IP address of the peer for which to create Permission.
*/
private TransportAddress ipAddress;
/**
* The time in milliseconds when the Permission will expire.
*/
private long expirationTime = -1;
/**
* Determines whether or not the Permission has expired.
*/
private boolean expired = false;
/**
* @param ipAddress contains the peer IP address and transport protocol to
* be assigned. The port value is ignored.
*/
public Permission(TransportAddress ipAddress)
{
this.setIpAddress(ipAddress);
this.setLifetime(Permission.MAX_LIFETIME);
}
/**
* @param ipAddress contains the peer IP address and transport protocol to
* be assigned. The port value is ignored.
* @param lifetime the lifetime of permission.
*/
public Permission(TransportAddress ipAddress, long lifetime)
{
this.setIpAddress(ipAddress);
this.setLifetime(lifetime);
}
/**
* @param ipAddress contains the peer IP address in String format.
* @param lifetime the lifetime of permission.
*/
public Permission(String ipAddress, long lifetime)
{
this.setIpAddress(ipAddress);
this.setLifetime(lifetime);
}
/**
* @return the ipAddress of the Permission as a TransportAddress.
*/
public TransportAddress getIpAddress()
{
return ipAddress;
}
/**
* @return the ipAddress as a String.
*/
public String getIpAddressString()
{
return this.getIpAddress().getHostAddress();
}
/**
* @param ipAddress the ipAddress of the peer for which to create
* Permission.
*/
public void setIpAddress(TransportAddress ipAddress)
{
this.ipAddress =
new TransportAddress(ipAddress.getHostAddress(), 0,
ipAddress.getTransport());
}
/**
* @param ipAddress the ipAddress as String of the peer for which to create
* Permission.
*/
public void setIpAddress(String ipAddress)
{
this.ipAddress = new TransportAddress(ipAddress, 0, Transport.UDP);
}
/**
* Returns the lifetime associated with this Permission.
* If the Permission is expired it returns 0.
*/
public long getLifetime()
{
if(!isExpired())
{
return (this.expirationTime-System.currentTimeMillis());
}
else
{
return 0;
}
}
/**
* Sets the time to expire in milli-seconds for this Permission.
* Max lifetime can be Permission.MAX_LIFEIME.
*
* @param lifetime the lifetime for this Permission.
*/
public void setLifetime(long lifetime)
{
synchronized(this)
{
this.expirationTime = System.currentTimeMillis()
+ Math.min(lifetime*1000, Permission.MAX_LIFETIME);
}
}
/**
* Refreshes the permission with the MAX_LIFETIME value.
*/
public void refresh()
{
this.setLifetime(Permission.MAX_LIFETIME);
}
/**
* refreshes the permission with given lifetime value.
* @param lifetime the required lifetime of permission.
*/
public void refresh(int lifetime)
{
this.setLifetime(lifetime);
}
/**
* Start the Permission. This launches the countdown to the moment the
* Permission would expire.
*/
public synchronized void start()
{
synchronized(this)
{
if (expirationTime == -1)
{
expired = false;
expirationTime = MAX_LIFETIME + System.currentTimeMillis();
}
else
{
throw new IllegalStateException(
"Permission has already been started!");
}
}
}
/**
* Determines whether this <tt>Permission</tt> is expired now.
*
* @return <tt>true</tt> if this <tt>Permission</tT> is expired
* now; otherwise, <tt>false</tt>
*/
public boolean isExpired()
{
return isExpired(System.currentTimeMillis());
}
/**
* Expires the Permission. Once this method is called the Permission is
* considered terminated.
*/
public synchronized void expire()
{
expired = true;
/*
* TurnStack has a background Thread running with the purpose of
* removing expired Permissions.
*/
}
/**
* Determines whether this <tt>Permission</tt> will be expired at
* a specific point in time.
*
* @param now the time in milliseconds at which the <tt>expired</tt> state
* of this <tt>Permission</tt> is to be returned
* @return <tt>true</tt> if this <tt>Permission</tt> will be
* expired at the specified point in time; otherwise, <tt>false</tt>
*/
public synchronized boolean isExpired(long now)
{
if (expirationTime == -1)
return false;
else if (expirationTime < now)
return true;
else
return expired;
}
/*
* The permission is uniquely identified by its IP address, so hashCode is
* calculated on the IP address only.
*/
@Override
public int hashCode()
{
return ipAddress.getHostAddress().hashCode();
}
/*
* Two Permissions are equal if their associated IP address, lifetime and
* transport protocol are same.
*/
@Override
public boolean equals(Object obj)
{
if (!(obj instanceof Permission))
{
return false;
}
Permission other = (Permission) obj;
if (ipAddress == null)
{
if (other.ipAddress != null)
{
return false;
}
}
else if (ipAddress.getHostAddress().compareTo(
other.ipAddress.getHostAddress()) != 0)
{
return false;
}
if (expirationTime != other.expirationTime)
{
return false;
}
return true;
}
@Override
public String toString()
{
return "Permission ["
+ (ipAddress != null ? "ipAddress=" + ipAddress : "") + "]";
}
}