{
transactionsMapping = new TransactionsMapping(
jiplet, serverTransaction);
// save server transaction side SipProvider in JipletDialog
Dialog serverDialog = serverTransaction.getDialog();
JipletDialog jd = jiplet.getDialog(serverDialog, true);
jd.setSipProvider((SipProvider) request.getSource());
}
}
catch (TransactionAlreadyExistsException e)
{
if (jiplet.isDebugEnabled() == true)
{
jiplet.debug("The request message to be proxied"
+ " is a retransmission, we drop it!");
}
}
}
}
// 2. Preprocess routing information (Section 16.4)
/*
* The proxy MUST inspect the Request-URI of the request. If the
* Request-URI of the request contains a value this proxy previously
* placed into a Record-Route header field (see Section 16.6 item
* 4), the proxy MUST replace the Request-URI in the request with
* the last value from the Route header field, and remove that value
* from the Route header field. The proxy MUST then proceed as if it
* received this modified request. ..... (idem to below:) 16.12. The
* proxy will inspect the URI in the topmost Route header field
* value. If it indicates this proxy, the proxy removes it from the
* Route header field (this route node has been reached).
*/
ListIterator routes = msg.getHeaders(RouteHeader.NAME);
if (routes != null)
{
if (routes.hasNext())
{
RouteHeader routeHeader = (RouteHeader) routes.next();
Address routeAddress = routeHeader.getAddress();
SipURI routeSipURI = (SipURI) routeAddress.getURI();
String h = routeSipURI.getHost();
int port = routeSipURI.getPort();
if (jiplet.hasAddress(h, port) == true)
{
if (jiplet.isDebugEnabled() == true)
{
jiplet
.debug("A request message to be proxied has this proxy in the route header. "
+ " We are going to remove the first route from "
+ " the RouteHeader");
}
routes.remove();
}
}
}
// 3. Determine target(s) for the request (Section 16.5)
/*
* The set of targets will either be predetermined by the contents
* of the request or will be obtained from an abstract location
* service. Each target in the set is represented as a URI.
*/
/*
* If the Request-URI of the request contains an maddr parameter,
* the Request-URI MUST be placed into the target set as the only
* target URI, and the proxy MUST proceed to Section 16.6.
*/
URI requestURI = msg.getRequestURI();
if (requestURI.isSipURI())
{
SipURI requestSipURI = (SipURI) requestURI;
if (requestSipURI.getMAddrParam() != null)
{
uris.clear();
uris.add(requestURI);
if (jiplet.isDebugEnabled() == true)
jiplet
.debug("While proxying a request, "
+ " the only target is the Request-URI (mAddr parameter)");
// 4. Forward the request
RequestForwarding forwarder = new RequestForwarding(jiplet,
this, request,
serverTransaction, stateful, addRecordRoute);
forwarder.forwardRequest(uris);
return;
}
}
if (stateful == true)
{
// Forward to next hop but dont reply OK right away for the
// BYE. Bye is end-to-end not hop by hop!
if (msg.getMethod().equals(Request.BYE))
{
if (serverTransaction == null)
{
if (jiplet.isDebugEnabled() == true)
jiplet
.debug("While proxying a request, null server transaction for BYE");
return;
}
Dialog d = serverTransaction.getDialog();
TransactionsMapping transactionsMapping = jiplet.getDialog(
d, true).getTransactionsMapping();
Dialog peerDialog = transactionsMapping
.getPeerDialog(serverTransaction);
Request clonedRequest = (Request) msg.clone();
FromHeader from = (FromHeader) clonedRequest
.getHeader(FromHeader.NAME);
from.removeParameter("tag");
ToHeader to = (ToHeader) clonedRequest
.getHeader(ToHeader.NAME);
to.removeParameter("tag");
if (peerDialog.getState() != null)
{
JipletDialog clientDialog = jiplet.getDialog(peerDialog, false);
SipProvider clientProvider = clientDialog.getSipProvider();
ListeningPoint lp = clientProvider.getListeningPoints()[0];
// TODO, need to save the right transport - save LP instead of SipProvider?
// (in JipletDialog)
ViaHeader via = jiplet.getHeaderFactory().createViaHeader(lp.getIPAddress(),
lp.getPort(), lp.getTransport(), null);
clonedRequest.addHeader(via);
ClientTransaction newct = clientProvider
.getNewClientTransaction(clonedRequest);
transactionsMapping
.addMapping(serverTransaction, newct);
peerDialog.sendRequest(newct);
jiplet.registerForResponse(clonedRequest, 60000L);
return;
}
else
{
// the peer dialog is not yet established so bail out.
// this is a client error - client is sending BYE
// before dialog establishment.
jiplet
.warn("While proxying a SIP request, bad dialog state - BYE dropped");
return;
}
}
// NEW CODE added by Amit to handle ACK and CANCEL
else if (msg.getMethod().equals(Request.ACK))
{
if (serverTransaction == null)
{
if (jiplet.isDebugEnabled() == true)
jiplet
.debug("While proxying an ACK request, null server transaction");
return;
}
Dialog d = serverTransaction.getDialog();
TransactionsMapping transactionsMapping = jiplet.getDialog(
d, true).getTransactionsMapping();
Dialog peerDialog = transactionsMapping
.getPeerDialog(serverTransaction);
Request clonedRequest = (Request) msg.clone();
if (peerDialog.getState() != null)
{
peerDialog.sendAck(clonedRequest);
}
return;
}
else if (msg.getMethod().equals(Request.CANCEL))
{
if (serverTransaction == null)
{
if (jiplet.isDebugEnabled() == true)
jiplet
.debug("While proxying a CANCEL request, null server transaction for BYE");
return;
}
Dialog d = serverTransaction.getDialog();
JipletDialog jd = jiplet.getDialog(d, true);
TransactionsMapping transactionsMapping = jd
.getTransactionsMapping();
Vector transactions = transactionsMapping