package org.cafesip.jiplet.sip;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import javax.sip.ClientTransaction;
import javax.sip.Dialog;
import javax.sip.DialogState;
import javax.sip.ServerTransaction;
import javax.sip.Transaction;
import org.cafesip.jiplet.Jiplet;
import org.cafesip.jiplet.JipletDialog;
import org.cafesip.jiplet.JipletLogger;
/**
* A class that manages mapping of client to server transactions.
*
* @version JAIN-SIP-1.1
*
* @author Olivier Deruelle <deruelle@nist.gov><br/>M. Ranganathan
* <mranga@nist.gov><br/><a href=" {@docRoot}/uncopyright.html">This
* code is in the public domain. </a>
*
*/
public class TransactionsMapping
{
private Jiplet jiplet;
private Hashtable table;
/** Creates new TransactionsTable */
public TransactionsMapping(Jiplet jiplet, ServerTransaction serverTransaction)
{
this.jiplet = jiplet;
Dialog serverDialog = serverTransaction.getDialog();
JipletDialog jd = jiplet.getDialog(serverDialog, true);
table = new Hashtable();
jd.setTransactionsMapping(this);
jd.setAttribute("firstTransaction", serverTransaction);
}
protected Dialog getPeerDialog(ServerTransaction serverTransaction)
{
if (table.containsKey(serverTransaction))
{
ClientTransaction ct = getClientTransaction(serverTransaction);
if (ct != null)
return ct.getDialog();
}
else
{
JipletDialog jdialog = jiplet.getDialog(serverTransaction.getDialog(),
false);
if (jdialog == null)
{
JipletLogger
.warn("Could not obtain the SIP dialog while finding the peer dialog."
+ " Cannot proxy anything to the peer");
return null;
}
Transaction transaction = (Transaction) jdialog.getAttribute("firstTransaction");
if (transaction == null)
{
JipletLogger
.warn("Could not find the first transaction while finding the peer dialog."
+ " Cannot proxy anything to the peer");
return null;
}
if (transaction instanceof ServerTransaction)
{
ClientTransaction ct = getClientTransaction((ServerTransaction) transaction);
if (ct != null)
return ct.getDialog();
}
else
{
ServerTransaction st = getServerTransaction((ClientTransaction) transaction);
if (st != null)
return st.getDialog();
}
}
return null;
}
protected ServerTransaction getServerTransaction(
ClientTransaction clientTransaction)
{
// Retrieve the good value:
Enumeration e = table.keys();
while (e.hasMoreElements())
{
ServerTransaction serverTransaction = (ServerTransaction) e
.nextElement();
Vector vector = (Vector) table.get(serverTransaction);
for (Enumeration en = vector.elements(); en.hasMoreElements();)
{
ClientTransaction ct = (ClientTransaction) en.nextElement();
if (ct == clientTransaction)
{
return serverTransaction;
}
}
}
return null;
}
protected ClientTransaction getClientTransaction(
ServerTransaction serverTransaction)
{
Vector vector = (Vector) table.get(serverTransaction);
if (vector == null)
return null;
else
{
for (Enumeration e = vector.elements(); e.hasMoreElements();)
{
ClientTransaction ct = (ClientTransaction) e.nextElement();
Dialog d = ct.getDialog();
if (d.getState() != null
&& d.getState().equals(DialogState.CONFIRMED))
return ct;
}
return null;
}
}
protected boolean hasMapping(ServerTransaction st)
{
if (!table.containsKey(st))
return false;
else
{
// retrieve the mapping from the table and check if is empty.
Vector vector = (Vector) table.get(st);
return !vector.isEmpty();
}
}
protected Vector getClientTransactions(ServerTransaction serverTransaction)
{
if (serverTransaction == null)
return null;
return (Vector) table.get(serverTransaction);
}
protected void addMapping(ServerTransaction serverTransaction,
ClientTransaction clientTransaction)
{
if (clientTransaction == null || clientTransaction.getDialog() == null)
{
return;
}
Vector clients = getClientTransactions(serverTransaction);
Dialog dialog = serverTransaction.getDialog();
JipletDialog jd = jiplet.getDialog(dialog, true);
TransactionsMapping map = jd.getTransactionsMapping();
Dialog clientDialog = clientTransaction.getDialog();
JipletDialog cjd = jiplet.getDialog(clientDialog, true);
cjd.setTransactionsMapping(map);
// save first transaction on client side, if this is the first
if (cjd.getAttribute("firstTransaction") == null)
{
cjd.setAttribute("firstTransaction", clientTransaction);
}
if (clients == null)
{
clients = new Vector();
table.put(serverTransaction, clients);
clients.addElement(clientTransaction);
}
else
{
for (Enumeration e = clients.elements(); e.hasMoreElements();)
{
// already exists so bail out.
if (clientTransaction == e.nextElement())
return;
}
clients.addElement(clientTransaction);
}
}
protected void removeMapping(ServerTransaction serverTransaction)
{
table.remove(serverTransaction);
}
protected void removeMapping(ClientTransaction clientTransaction)
{
ServerTransaction serverTransaction = getServerTransaction(clientTransaction);
Vector clientTransactions = getClientTransactions(serverTransaction);
if (clientTransactions != null && clientTransactions.isEmpty()) // ???
{
clientTransactions.removeElement(clientTransaction);
table.remove(serverTransaction); // ?? (only if no other clients left?)
}
}
protected void printTransactionsMapping()
{
synchronized (table)
{
Enumeration e = table.keys();
while (e.hasMoreElements())
{
ServerTransaction serverTransaction = (ServerTransaction) e
.nextElement();
Vector vector = (Vector) table.get(serverTransaction);
if (vector != null)
{
for (int i = 0; i < vector.size(); i++)
{
ClientTransaction clientTransac = (ClientTransaction) vector
.elementAt(i);
}
}
}
}
}
}