/*
* Created on Nov 13, 2004
*
*/
package org.cafesip.reference.jiplet;
import java.io.IOException;
import java.text.ParseException;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.ArrayList;
import javax.sip.RequestEvent;
import javax.sip.SipException;
import javax.sip.SipProvider;
import javax.sip.header.ContactHeader;
import javax.sip.header.ExpiresHeader;
import javax.sip.header.FromHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
import org.cafesip.jiplet.Jiplet;
import org.cafesip.jiplet.JipletException;
import org.cafesip.jiplet.JipletLogger;
import org.cafesip.jiplet.JipletRequest;
import org.cafesip.jiplet.JipletSignal;
import org.cafesip.jiplet.JipletTimer;
import org.cafesip.jiplet.Pair;
import org.cafesip.jiplet.TimerEvent;
import org.cafesip.jiplet.config.jip.InitParam;
import org.cafesip.jiplet.config.jip.InitParams;
import org.cafesip.jiplet.config.jip.JipletConfig;
/**
* @author amit
*
*/
public class SipRegistrar extends Jiplet
{
// timer that wakes up every minite and checks for expired registrations
private TimerEvent timer = null;
private ExternalEntity entity;
/**
*
*/
public SipRegistrar()
{
}
/*
* @see org.cafesip.jiplet.Jiplet#init(org.cafesip.jiplet.config.jip.Jiplet)
*/
public void init(JipletConfig config) throws JipletException
{
info(" being initialized");
// The following code segment has no purpose other than demonstrating
// how
// init parameters can be accessed. It also demonstrates how
// application-
// scope variables can be set.
if (isDebugEnabled() == true)
{
InitParams init = config.getInitParams();
Iterator iter = init.getInitParam().iterator();
while (iter.hasNext() == true)
{
InitParam parm = (InitParam) iter.next();
debug("Init param (" + parm.getParamName() + ", "
+ parm.getParamValue() + ")");
// save the variables in the application scope
getJipletContext().setAttribute(parm.getParamName(),
parm.getParamValue());
}
}
try
{
// start an external entity so that it can send events to the jiplet when a TCP message is
// received from an external application. This illustrates how to use signaling.
entity = new ExternalEntity(getJipletContext(), getName(), -1);
entity.start();
}
catch (IOException e)
{
error("Could not start the external entity : " + e.getMessage()
+ "\n" + JipletLogger.getStackTrace(e));
}
}
/*
* @see org.cafesip.jiplet.Jiplet#doRegister(javax.sip.RequestEvent)
*/
public void doRegister(JipletRequest requestEvent)
{
try
{
if (timer == null)
{
timer = startTimer(60000L, true, requestEvent, null);
}
RequestEvent req_event = requestEvent.getRequestEvent();
SipProvider provider = (SipProvider) req_event.getSource();
Request req_msg = req_event.getRequest();
FromHeader from = (FromHeader) req_msg.getHeader(FromHeader.NAME);
long expires = 60L * 60L * 1000L; // default 60 minutes
ExpiresHeader ehead = (ExpiresHeader) req_msg
.getHeader(ExpiresHeader.NAME);
ContactHeader contact = (ContactHeader) req_msg
.getHeader(ContactHeader.NAME);
if (ehead != null)
{
expires = ehead.getExpires() * 1000L;
}
else
{
if (contact != null)
{
int e = contact.getExpires();
if (e >= 0)
{
expires = e * 1000L;
}
}
}
String user = requestEvent.getUserPrincipal().getName();
String uri = from.getAddress().getURI().toString();
ContactInfo c = null;
if (expires == 0)
{
info("User " + user + " logged out");
LocationDatabase.getInstance().remove(uri);
}
else
{
String priv = requestEvent.isUserInRole("user") == true? "user": "other";
info("User " + user + " logged in"
+ " from URI: " + uri
+ " (" + priv + ")");
c = new ContactInfo(contact,
new Date( (new Date()).getTime() + expires) );
LocationDatabase.getInstance().put(uri, c);
}
// send a OK response
sendAuthSuccess(req_msg, provider);
debug("Sent a OK response to the registration message");
// pass this information to the presence service so notifications can be sent out
Pair status = new Pair(uri, c);
requestEvent.setAttribute("registrationInfo", status);
forward(requestEvent, "ExamplePresenceServiceJiplet");
}
catch (Exception ex)
{
fatal(ex.getClass().getName() + ": " + ex.getMessage() + "\n"
+ JipletLogger.getStackTrace(ex));
}
}
private void sendAuthSuccess(Request request, SipProvider provider)
throws ParseException, SipException
{
Response response = getMessageFactory().createResponse(Response.OK,
request);
provider.sendResponse(response);
}
/*
* @see org.cafesip.jiplet.Jiplet#destroy()
*/
public void destroy()
{
if (timer != null)
{
cancelTimer(timer);
timer = null;
}
if (entity != null)
{
if (entity.isAlive() == true)
{
entity.interrupt();
}
}
}
/*
* @see org.cafesip.jiplet.Jiplet#processTimer(org.cafesip.jiplet.JipletTimer)
*/
public void processTimer(JipletTimer timer)
{
debug ("The timer has expired. Checking for expired registration");
long d = (new Date()).getTime();
ArrayList expired_list = new ArrayList();
Iterator iter = LocationDatabase.getInstance().entrySet().iterator();
while (iter.hasNext() == true)
{
Map.Entry entry = (Map.Entry)iter.next();
String key = (String)entry.getKey();
ContactInfo value = (ContactInfo)entry.getValue();
if (d >= value.getExpiryTime().getTime())
{
info ("Entry " + key + " has expired. retiring the user.");
iter.remove();
expired_list.add(key);
}
}
if (expired_list.isEmpty() == false)
{
timer.setAttribute("expiredRegistrations", expired_list);
forward(timer, "ExamplePresenceServiceJiplet");
}
}
/*
* @see org.cafesip.jiplet.Jiplet#processSignal(org.cafesip.jiplet.JipletSignal)
*/
public void processSignal(JipletSignal signal)
{
super.processSignal(signal); // print the debug message
String message = (String)signal.getEventObject();
JipletLogger.info("Received a signal with message " + message);
}
}