• No se han encontrado resultados

This section is intended for application developers. The concepts relevant to application developers are discussed, including how an application indicates its routing intention, and what additional information related to application composition an application can obtain from the container.

17.2.1 Receiving an Initial Request

When an application is invoked to service an initial request, the container calls the application's doXXX() method with the SipServletRequest in a new SipSession. The application can obtain the identity of the subscriber that the application is serving, and the routing region in which it is invoked from the SipSession object. These attributes do not change throughout the lifetime of the SipSession object.

17.2.2 Sending an Initial Request

Whenever an application proxies or sends an initial request, the container invokes the Application Router to obtain the name of the next application that should service the request. The Application Router needs to know whether the sent request is related to a request that the application has received earlier. Though related, the new request could be a modified version of the originally received request or a brand new request. If the sent request is not related to any received request, the Application Router starts a new application selection process. On the other hand, if the sent

request is related to a received request, the Application Router makes use of state information associated with the received request, and resumes the selection process from the previous state. This is crucial to the selection of applications. As an example, consider a deployment where all initial INVITE requests received by the container are serviced by two applications, A and B, in this order. When an INVITE request is received externally, or if an application Z acts as a UAC and sends a INVITE request, the container invokes the Application Router. The Application Router starts the selection process from the beginning and selects A. When A is invoked and proxies the INVITE request, again the container invokes the Application Router. Now, the Application Router must be made aware that this is related to the previous request so that it can determine that A has already been invoked and that B must be invoked as the next application. When an application acts as a UAC and sends a request, the request is not based on any previously received request. That is, the application intends the request to be regarded as a new request unrelated to any other request. Although the application intention is implicit in this case, it is clear that a new application selection process should take place.

Listing 17-1 Application acts as UAC and sends initial request

+---+ | | | req = factory.createRequest | | (appSession, | req | "INVITE", from, to); |---> | req.send(); |

| | +---+

req starts a new selection process

In the case of a proxy application, there is no ambiguity. It is clear that the application's intention is to send the request along the way, or in other words to continue the call.

Listing 17-2 Application proxies an initial request

+---+ req1 | | req2 --->| proxy = req1.getProxy(); |---> | proxy.proxyTo(...); | | | +---+

A p p l i c a t i on E n v i r o nm e n t a n d B e h a v i o ur

req2 is a continuation of req1

If the application acts a B2BUA, and uses the SipFactory.createRequest(SipServletRequest origRequest, boolean sameCallId) or B2buaHelper.createRequest(SipServletRequest origRequest, Map headers) methods, then again it is clear the the application's intention is to continue the call.

Listing 17-3 Application acts as B2BUA to relay initial request

+---+ req1 | | req2 --->| req2 = factory.createRequest(req1, ...); |---> | req2.send(); | | | +---+

req2 is a continuation of req1

In the cases encountered so far, the application intentions are clear from context. Such intentions are referred to as routing directives. In the first case the application implicitly signaled a NEW directive, and in the second and third cases the application implicitly signaled a CONTINUE directive.

Unlike the cases described above, there are times where an explicit directive is required.

Listing 17-4 Application acts as B2BUA to relay initial request and signals the CONTINUE directive explcitly

+---+ | |

req1 | req2 = factory.createRequest(appSession, | req2 --->| "INVITE", newFrom, req1.getTo()); |---> | // copy headers and content from req1 |

| req2.setRoutingDirective(CONTINUE, req1);| | req2.send(); | +---+

In case, an application wishes to send a new request based on a received request but intends the request to be regarded as a new request, thereby initiating a new selection process. The

application could create the new request separately and copy all the headers and content, but it is far easier to create the request based on an existing request and then indicate a routing directive explicitly by making use of a method in the SipServletRequest class introduced in version 1.1, setRoutingDirective(SipApplicationRoutingDirective dir, SipServletRequest req)

Listing 17-5 Application acts as B2BUA to send NEW request

+---+ req1 | | req2 - - - ->| req2 = factory.createRequest(req1, ...); |---> | req2.setRoutingDirective(NEW, null); | | req2.send(); | | | +---+ req2 is a NEW

In the above case, a new application selection process will begin for the req2.

Finally, a third directive, REVERSE, is necessary but is used less commonly. REVERSE is used when an application reverses the direction of the call. There are two cases. In the first case, an application invoked to service the caller for an initial request now wishes to place a call back to the caller. A practical example is a Call Waiting (CW) application. When a subscriber to CW places a call, CW is invoked to serve the caller. When this call is still up, the subscriber receives an incoming call. CW alerts the subscriber, who then activates CW to put the first callee on hold, and switch to the new caller. If the subscriber finishes the conversation with the new caller and hangs up the phone, forgetting that there is another call on hold, the CW feature places a call to the subscriber. In this call, the subscriber is now the callee.

In the second case, an application which is invoked to service the callee in a request, now wishes to place a call on behalf of that same subscriber as the caller. A practical example is a three-way calling (3WC) application. When the subscriber receives a call, the 3WC application is invoked to serve the subscriber as the callee. In the middle of the call, the subscriber activates the 3WC application to call a third person, with the subscriber as the caller.

In both cases, the direction of the call is reversed, and the applications must specify the REVERSE directive so the Application Router is able to select the next application correctly.

A p p l i c a t i on E n v i r o nm e n t a n d B e h a v i o ur

Listing 17-6 Application reversing the call direction by placing a call back to the caller

+---+ | | req1 | req2 = factory.createRequest(appSession, | --->| "INVITE", newFrom, req1.getFrom(),...);| Caller | // copy headers and content from req1 | req2 | req2.setRoutingDirective(REVERSE, req1); | <---| req2.send(); | +---+

req2 is a REVERSE

It is important to note that in the cases where an application is sending a request based on a previously received request, the transaction of the received request may have completed, or indeed the SIP dialog may have completed and terminated. Indeed, in 3WC the transaction is already completed, and in busy retry the SIP dialog has already terminated. The application may store the request for later use. Note also that the second argument to setRoutingDirective must be an initial request received by the application, i.e.SipServletRequest.isInitial() must be true. The following table summarizes the routing directive under different scenarios:

Note: If recursion is enabled, and the container automatically proxies to contact addresses received in redirect (3xx) responses, these requests are treated as if the application explicitly called proxyTo() to proxy to these contact addresses. Therefore they also have the CONTINUE directive.

Table 17-1 Routing Directives

Application Action Directive

Req =

factory.createRequest(appSession, "INVITE", from, to);

NEW request.getProxy().proxyTo() CONTINUE req2 = factory.createRequest(req1, ...); req2.send(); CONTINUE req2.setRoutingDirective(directive, req1); Explicit directive