* 10. Forward the new request
*
* 11. Set timer C
*/
HeaderFactory headerFactory = jiplet.getHeaderFactory();
AddressFactory addressFactory = jiplet.getAddressFactory();
// Get the parameters and the transport of the request URI
URI requestURI = requestEvent.getRequest().getRequestURI();
Iterator parametersNames = null;
if (requestURI.isSipURI())
{
parametersNames = ((SipURI) requestURI).getParameterNames();
// this is how the JAIN-SIP jiplet guys have done it but it seems
// problematic. Why?
// transport = ((SipURI) requestURI).getTransportParam();
}
for (int i = 0; i < targetsURIList.size(); i++)
{
URI targetURI = (URI) targetsURIList.get(i);
// Copy the parameters and the transport in the new Request URI
// of the cloned Request
//
// 1. Make a clone of the received request
//
//
Request clonedRequest = (Request) requestEvent.getRequest().clone();
//
// 2. Update the Request-URI
//
/*
* The Request-URI in the copy's start line MUST be replaced with
* the URI for this target. If the URI contains any parameters not
* allowed in a Request-URI, they MUST be removed.
*
* This is the essence of a jiplet's role. This is the mechanism
* through which a jiplet routes a request toward its destination.
*
* In some circumstances, the received Request-URI is placed into
* the target set without being modified. For that target, the
* replacement above is effectively a no-op.
*
*/
// All the targets URI are already canonicalized
if (requestURI.isSipURI())
{
clonedRequest.setRequestURI(targetURI);
}
//
// 3. Max-Forwards
//
/*
* If the copy contains a Max-Forwards header field, the jiplet MUST
* decrement its value by one (1). If the copy does not contain a
* Max-Forwards header field, the jiplet MUST add one with a field
* value, which SHOULD be 70.
*/
MaxForwardsHeader mf = (MaxForwardsHeader) clonedRequest
.getHeader(MaxForwardsHeader.NAME);
if (mf == null)
{
mf = headerFactory.createMaxForwardsHeader(70);
clonedRequest.addHeader(mf);
}
else
{
int max = mf.getMaxForwards() - 1;
mf.setMaxForwards(max);
}
//
// 4. Record-Route
//
/*
* The URI placed in the Record-Route header field value MUST be a
* SIP or SIPS URI. This URI MUST contain an lr parameter (see
* Section 19.1.1). This URI MAY be different for each destination
* the request is forwarded to. The URI SHOULD NOT contain the
* transport parameter.
*/
ListeningPoint defaultLP = jiplet.getListeningPointDefault();
SipProvider sipProvider = jiplet.getSipProvider(defaultLP);
if (addRecordRoute)
{
// Only in stateful forwarding
// We add our jiplet RecordRoute header to the top of the
// list - use the following recommended mechanism to handle multi-homing
/*
* If the URI placed in the Record-Route header field needs to
* be rewritten when it passes back through in a response, the
* URI MUST be distinct enough to locate at that time. (The
* request may spiral through this proxy, resulting in more than
* one Record-Route header field value being added). Item 8 of
* Section 16.7 recommends a mechanism to make the URI
* sufficiently distinct.
*
* The proxy MAY include parameters in the Record-Route header
* field value. These will be echoed in some responses to the
* request such as the 200 (OK) responses to INVITE. Such
* parameters may be useful for keeping state in the message
* rather than the proxy.
*/
if (stateful)
{
SipURI sipURI = addressFactory.createSipURI(null, defaultLP
.getIPAddress());
sipURI.setPort(defaultLP.getPort());
sipURI.setTransportParam(defaultLP.getTransport());
sipURI.setLrParam();
// save the IP address and port the request came in on, for
// rewriting the record route header later in the response
// put it in this forwarded message itself - user part of RR
SipProvider sourceProvider = (SipProvider) requestEvent
.getSource();
ListeningPoint sourceLp = sourceProvider
.getListeningPoints()[0];
sipURI.setUser(sourceLp.getIPAddress() + '-' + sourceLp.getPort());
Address address = addressFactory
.createAddress(null, sipURI);
RecordRouteHeader recordRouteHeader = headerFactory
.createRecordRouteHeader(address);
ListIterator recordRouteHeaders = clonedRequest
.getHeaders(RecordRouteHeader.NAME);
clonedRequest.removeHeader(RecordRouteHeader.NAME);
ArrayList v = new ArrayList();
v.add(recordRouteHeader);
// add the other record route headers.
while (recordRouteHeaders != null
&& recordRouteHeaders.hasNext())
{
recordRouteHeader = (RecordRouteHeader) recordRouteHeaders
.next();
v.add(recordRouteHeader);
}
for (int j = 0; j < v.size(); j++)
{
recordRouteHeader = (RecordRouteHeader) v.get(j);
clonedRequest.addHeader(recordRouteHeader);
}
}
}
//
// 5. Add Additional Header Fields
//
// No Additional headers to add...
//
// 6. Postprocess routing information
//
/*
* If the copy contains a Route header field, the jiplet MUST
* inspect the URI in its first value. If that URI does not contain
* an lr parameter, the jiplet MUST modify the copy as follows: -
* The jiplet MUST place the Request-URI into the Route header field
* as the last value. - The jiplet MUST then place the first Route
* header field value into the Request-URI and remove that value
* from the Route header field.
*/
// Strip first route if it is the jiplet UIR adn lr parameter
ListIterator routes = clonedRequest.getHeaders(RouteHeader.NAME);
if (routes != null && routes.hasNext())
{
RouteHeader routeHeader = (RouteHeader) routes.next();
Address routeAddress = routeHeader.getAddress();
URI routeURI = routeAddress.getURI();
if (routeURI.isSipURI() && ((SipURI) routeURI).hasLrParam())
{
String host = ((SipURI) routeURI).getHost();
int port = ((SipURI) routeURI).getPort();
if (jiplet.hasAddress(host, port))
{
routes.remove();
}
}
}
//
// 7. Determine Next-Hop Address, Port, and Transport
//
/*
* the jiplet applies the procedures listed in [4] as follows to
* determine where to send the request. If the jiplet has
* reformatted the request to send to a strict-routing element as
* described in step 6 above, the jiplet MUST apply those procedures
* to the Request-URI of the request. Otherwise, the jiplet MUST
* apply the procedures to the first value in the Route header
* field, if present, else the Request-URI. The procedures will
* produce an ordered set of (address, port, transport) tuples.
* Independently of which URI is being used as input to the
* procedures of [4], if the Request-URI specifies a SIPS resource,
* the jiplet MUST follow the procedures of [4] as if the input URI
* were a SIPS URI.
*/
// Determine Next-Hop Address, Port, and Transport will be done by
// the stack.
//
// 8. Add a Via header field value
//
/*
* The jiplet MUST insert a Via header field value into the copy
* before the existing Via header field values.
*/
ViaHeader viaHeader = null;
String transport = defaultLP.getTransport();
if (clonedRequest.getMethod().equals(Request.CANCEL))
{
// Branch Id will be assigned by the stack.
viaHeader = headerFactory.createViaHeader(defaultLP.getIPAddress(),
defaultLP.getPort(), transport != null ? transport : "", null);
// Cancel is hop by hop so remove all other via headers.
clonedRequest.removeHeader(ViaHeader.NAME);
}
else
{
String branch = ProxyUtilities.generateBranchId();
viaHeader = headerFactory.createViaHeader(defaultLP.getIPAddress(),
defaultLP.getPort(), transport != null ? transport : "", branch);
}
if (viaHeader != null)
clonedRequest.addHeader(viaHeader);