* failure to send the response or signal a timeout in its state
* machine. These errors would be logged for diagnostic purposes as
* appropriate, but the protocol requires no remedial action from
* the jiplet.
*/
ServerTransaction serverTransaction = transactionsMapping
.getServerTransaction(clientTransaction);
// For forking:
if ((response.getStatusCode() == Response.UNAUTHORIZED || response
.getStatusCode() == Response.DECLINE)
&& serverTransaction != null)
{
// check the busy or decline
Vector clientsTransactionList = transactionsMapping
.getClientTransactions(serverTransaction);
if (clientsTransactionList != null
&& clientsTransactionList.size() > 1)
{
transactionsMapping.removeMapping(clientTransaction);
}
}
// For forking:
if (response.getStatusCode() == Response.OK
&& serverTransaction != null)
{
Dialog peerDialog = serverTransaction.getDialog();
Vector clientsTransactionList = transactionsMapping
.getClientTransactions(serverTransaction);
if (peerDialog != null && peerDialog.getState() != null
&& peerDialog.getState().equals(DialogState.CONFIRMED)
&& clientsTransactionList != null
&& clientsTransactionList.size() > 1)
{
Dialog dialog = clientTransaction.getDialog();
Request byeRequest = dialog.createRequest(Request.BYE);
ClientTransaction ct = responseProvider
.getNewClientTransaction(byeRequest);
dialog.sendRequest(ct);
// we have to remove the transaction from the table:
transactionsMapping.removeMapping(clientTransaction);
return;
}
else
{
if (serverTransaction != null)
transactionsMapping.addMapping(serverTransaction,
clientTransaction);
}
}
if (serverTransaction == null)
{
ListeningPoint defaultLP = jiplet.getListeningPointDefault();
jiplet.getSipProvider(defaultLP).sendResponse(response);
return;
}
else
{
// we can try to modify the tags:
Dialog dialog = serverTransaction.getDialog();
if (dialog != null)
{
String localTag = dialog.getLocalTag();
String remoteTag = dialog.getRemoteTag();
ToHeader toHeader = (ToHeader) response
.getHeader(ToHeader.NAME);
FromHeader fromHeader = (FromHeader) response
.getHeader(FromHeader.NAME);
if (localTag != null && remoteTag != null)
{
if (dialog.isServer())
{
toHeader.setTag(localTag);
}
else
{
fromHeader.setTag(remoteTag);
}
}
}
// 8. Record-Route - modify record route header if needed
/*
* If the selected response contains a Record-Route header field
* value originally provided by this proxy, the proxy MAY choose
* to rewrite the value before forwarding the response. This
* allows the proxy to provide different URIs for itself to the
* next upstream and downstream elements. A proxy may choose to
* use this mechanism for any reason. For instance, it is useful
* for multi-homed hosts.
*/
ListIterator rrHeaders = response
.getHeaders(RecordRouteHeader.NAME);
while (rrHeaders.hasNext())
{
// look for the 1st one to replace, replace it & get out
RecordRouteHeader rr = (RecordRouteHeader) rrHeaders.next();
URI uri = rr.getAddress().getURI();
if (uri instanceof SipURI)
{
SipURI sipURI = (SipURI) uri;
// is this a record route header we added?
if (jiplet.hasAddress(sipURI.getHost(), sipURI
.getPort()))
{
// does this one need replacing?
String user = sipURI.getUser();
if (user != null)
{
StringTokenizer tok = new StringTokenizer(user,
"-");
if (tok.countTokens() == 2)
{
SipURI sourceURI = jiplet
.getAddressFactory().createSipURI(
null, tok.nextToken());
sourceURI.setPort(Integer.valueOf(
tok.nextToken()).intValue());
sourceURI.setLrParam();
// rewrite it back into the RR header
rr.getAddress().setURI(sourceURI);
rrHeaders.set(rr);
break;
}
}
}
}
}
try
{
serverTransaction.sendResponse(response);
}
catch (InvalidArgumentException e)
{
// this exception only happens if the Response was created
// by Dialog.createReliableProvisionalResponse(int) and the