[Users] WeSIP b2bua problem

Ginés Gómez gines at voztele.com
Thu Mar 8 23:24:46 CET 2007


Hi,

	the procedure for downstream cancel looks OK at 90% but there is  
something I don't understand. Why do you set the Request URI of the  
CANCEL request with 'cancelRequest.setRequestURI(requestUri)' ? The  
'downstreamRequest.createCancel()' will generate a CANCEL request  
with the proper RURI. This could be the cause of the error. Another   
possible cause is that you have received a final response to the  
downstream dialog while processing the CANCEL. Can you capture the  
IllegalStateException and try to send a BYE to the downstream to see  
wether it works ?

Regards

Gines
	
El 08/03/2007, a las 19:15, tele escribió:

> The C is my case, during ringing i cancel the call from caller or the
> called.
> so i'm try to do something like this:
>
> protected void doCancel(SipServletRequest req) throws  
> ServletException,
> IOException {
>         SipSession downstremLeg =
> (SipSession)req.getSession().getApplicationSession().getAttribute 
> ("downstreamLeg");
>         SipServletRequest downstreamRequest =
> (SipServletRequest)downstreamLeg.getAttribute("initialRequest");
>         SipServletRequest cancelRequest = (SipServletRequest)
> downstreamRequest.createCancel();
>         SipURI requestUri = sf.createSipURI(((SipURI)
> req.getRequestURI()).getUser(),((SipURI)
> req.getRequestURI()).getHost());
>         cancelRequest.setRequestURI(requestUri);
>         cancelRequest.send();
> }
>
> get the initial invite generated in UAC for the downstream leg and
> create a cancel request for the leg, and send it.
> unfortunaly this not work and i'm occuring in exception:
>
> SipProcessor     [SipProcessor[4]] - error processing event...
> java.lang.IllegalStateException
>         at
> com.voztele.sipservlet.core.SipResponse.send(SipResponse.java:144)
>         at
> com.voztele.sipservlet.valves.ConvergedHostValve.invokeSipRequest 
> (ConvergedHostValve.java:283)
>         at
> com.voztele.sipservlet.valves.ConvergedHostValve.invokeSIP 
> (ConvergedHostValve.java:126)
> etc.......
>
> i think the logic for cancel the other leg is correct but i'm doing
> something wrong :)
>
> regards
>
> :tele
>
>
>
> On Thu, 2007-03-08 at 13:30 +0100, Ginés Gómez wrote:
>>
>> C) You have not answered to the upstream INVITE with a final response
>>
>>    - The container will automatically send a 200OK to the CANCEL
>>    - The container will automatically send a 487 response to the   
>> INVITE
>>    - The application will receive the CANCEL request in the doCancel
>> method
>>        - The application sends a CANCEL to the downstream dialog if
>> it is not completed
>>        - The application sends a BYE to the downstream dialog if it
>> is completed
>>    - Any attempt to answer (or proxy) the incoming INVITE will cause
>> an IllegalStateException to be thrown
>>
>> Hope I was of some help
>>
>> Regards
>>
>> Gines
>>
>>
>> El 08/03/2007, a las 12:31, tele escribió:
>>
>>> Hi,
>>>
>>> I'm so closer to complete the basic b2bua but i need last
>>> clarification
>>> about the CANCEL.
>>>
>>> The specification of servlet API said:
>>>
>>> Receiving CANCEL
>>> When a CANCEL is received for a request which has been passed to an
>>> application, and the appli-
>>> cation has not responded yet or proxied the original request, the
>>> container responds to the original
>>> request with a 487 (Request Terminated) and to the CANCEL with a
>>> 200 OK
>>> final response, and it
>>> notifies the application by passing it a SipServletRequest object
>>> representing the CANCEL
>>> request. The application should not attempt to respond to a request
>>> after receiving a CANCEL for
>>> it. Neither should it respond to the CANCEL notification.
>>> Clearly, there is a race condition between the container generating
>>> the
>>> 487 response and the SIP
>>> servlet generating its own response. This should be handled using
>>> standard Java mechanisms for
>>> resolving race conditions. If the application wins, it will not be
>>> notified that a CANCEL request
>>> was received. If the container wins and the servlet tries to send a
>>> response before (or for that matter
>>> after) being notified of the CANCEL, the container throws an
>>> IllegalStateException.
>>>
>>> I should not override the method onCancel?
>>> it's not clear to me what to do.
>>>
>>> anyway the CANCEL didn't go to the other 'leg'.
>>>
>>>
>>> thanks!
>>>
>>>
>>> :tele
>>>
>>>
>>> On Wed, 2007-03-07 at 16:36 +0100, tele wrote:
>>>> I've solve my stupid problem.
>>>>
>>>> The problem was in my change of Call-ID that i need for my
>>>> requirements.
>>>> In the code with problem i did the custom change after create  
>>>> the new
>>>> Request.
>>>>
>>>>                 SipServletRequest downstreamReq =
>>>> sf.createRequest(req,false);
>>>>
>>>>                 //Retrieve SipApplicationSession and SipSessions
>>>>                 SipApplicationSession sas =
>>>> req.getSession().getApplicationSession();
>>>>
>>>>                 // change call-id
>>>>                 String oldcid = downstreamReq.getCallId();
>>>>                 downstreamReq.removeHeader("Call-ID");
>>>>                 downstreamReq.addHeader("Call-ID","1111" + oldcid);
>>>>
>>>> do my change before create the downstreamReq solve my problem.
>>>>
>>>> :tele
>>>>
>>>>
>>>> On Mon, 2007-03-05 at 22:50 +0100, tele wrote:
>>>>> Hi gines,
>>>>>
>>>>> You have been very clear! now i've understand the "dialog
>>>>> marking" but i
>>>>> cannot get my b2bua test working.
>>>>> i'll add more debug to see why the BYE generated is incorrect in
>>>>> case of
>>>>> hangup from the caller.
>>>>>
>>>>> hem... another question:
>>>>> how can i get the Logger reference of the  Servlet for adding
>>>>> more debug?
>>>>> or i need to create a new logger with log4j and write log to a
>>>>> new file.
>>>>>
>>>>> anyway attached there is the full source code for now.
>>>>>
>>>>> thank you very much :)
>>>>>
>>>>> regards,
>>>>>
>>>>> :tele
>>>>>
>>>>>
>>>>> Ginés Gómez wrote:
>>>>>> Hi ,
>>>>>>
>>>>>> I understand. I'll try to explain myself clearer. Let's go  
>>>>>> back to
>>>>>> your original code. This is extracted from the doInvite method.
>>>>>> Here
>>>>>> you save both call legs in the application session
>>>>>> .....
>>>>>>
>>>>>> //Save reference to SipSessions in the SipApplication
>>>>>> sas.setAttribute("upstreamLeg",upstreamLeg);
>>>>>> sas.setAttribute("downstreamLeg",downstreamLeg);
>>>>>> .....
>>>>>>
>>>>>> what I suggest is that you do the following (after saving in
>>>>>> ApplicationSession)
>>>>>>
>>>>>> upstreamLeg.setAttribute("COUNTERPART_LEG",downstreamLeg);
>>>>>> downstreamLeg.setAttribute("COUNTERPART_LEG",upstreamLeg);
>>>>>>
>>>>>> this way, at any time, you can always get a reference to the
>>>>>> counterpart dialog doing
>>>>>>
>>>>>> req.getSession().getAttribute("COUNTERPART_LEG");
>>>>>>
>>>>>> then, when receiving the BYE
>>>>>>
>>>>>>>> protected void doBye(SipServletRequest req) throws
>>>>>>>> ServletException,IOException{
>>>>>>>>
>>>>>>>>     //Answer positively
>>>>>>>>     request.createResponse(200,"Have a nice day").send();
>>>>>>>>
>>>>>>>>     //Mark my dialog as finished
>>>>>>>>     request.getSession().setAttribute("FINISHED","OK");
>>>>>>>>
>>>>>>>>     //Get the other leg and finish it in case it is not  
>>>>>>>> finished
>>>>>>>>
>>>>>>>>     //Note how useful is to have in both SipSessions (that is,
>>>>>>>> both
>>>>>>>> legs) an attribute which refers the
>>>>>>>>     //other leg involved in the B2BUA transaction.
>>>>>>>>     SipSession counterPartLeg= (SipSession)
>>>>>>>> request.getSession.getAttribute("COUNTERPART_LEG");
>>>>>>>>     if (counterPartLeg.getAttribute("FINISHED")==null){
>>>>>>>>     counterPartLeg.createRequest("BYE").send();
>>>>>>>>     }
>>>>>>>> }
>>>>>>
>>>>>> as you'll see what I do is sending BYE to the 'other' leg. I  
>>>>>> don't
>>>>>> care wether I'm processing upstream or downstream because the
>>>>>> COUNTERPART_LEG attribute in the SipSession will always return a
>>>>>> reference to the counterpart SipSession. Since the processing
>>>>>> (answer
>>>>>> OK, send BYE the other leg) is simetrical regardless the BYE was
>>>>>> received from the upstream or the downstream the method will work
>>>>>>
>>>>>> :-)
>>>>>>
>>>>>> Regards
>>>>>>
>>>>>> Gines
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>>    protected void doBye(SipServletRequest req) throws
>>>>>>> ServletException,
>>>>>>> IOException {
>>>>>>>         req.createResponse(200,"OK").send();
>>>>>>>         SipSession downstreamLeg =
>>>>>>> (SipSession)req.getSession().getApplicationSession
>>>>>>> ().getAttribute("downstreamLeg");
>>>>>>>
>>>>>>>         SipServletRequest byeRequest =
>>>>>>> downstreamLeg.createRequest("BYE");
>>>>>>>         byeRequest.send();
>>>>>>>    }
>>>>>>>
>>>>>>> this works only when the BYE come from called.
>>>>>>>
>>>>>>> maybe i can get the Id of session of the current request
>>>>>>> arrived in
>>>>>>> doBye with getId() and do a check for the other id in the
>>>>>>> upstreamLeg
>>>>>>> and downstreamLeg then if equals to any of this, generate the  
>>>>>>> BYE
>>>>>>> request in the other call-leg.
>>>>>>>
>>>>>>> pseudo code:
>>>>>>>
>>>>>>> String sessionId (SipSession)req.getSession().getId();
>>>>>>> SipSession upSession =
>>>>>>> (SipSession)req.getSession().getApplicationSession
>>>>>>> ().getAttribute("upstreamLeg");
>>>>>>>
>>>>>>> SipSession downSession =
>>>>>>> (SipSession)req.getSession().getApplicationSession
>>>>>>> ().getAttribute("downstreamLeg");
>>>>>>>
>>>>>>>
>>>>>>> if (sessionId == upSession.getId())
>>>>>>> {
>>>>>>>    // create and send BYE request in the upstreamLeg
>>>>>>>    ....
>>>>>>> } else {
>>>>>>>    // create and send BYE request in the downstreamLeg
>>>>>>>    ....
>>>>>>> };
>>>>>>>
>>>>>>>
>>>>>>> regards,
>>>>>>>
>>>>>>> :tele
>>>>>>>
>>>>>>>
>>>>>>> On Mon, 2007-03-05 at 15:27 +0100, Ginés Gómez wrote:
>>>>>>>> Anyway.... when doing B2BUA you tipically don't need to wait  
>>>>>>>> for
>>>>>>>> 200OK to generate BYE response. You can simply send a 200OK to
>>>>>>>> any
>>>>>>>> incoming BYE request (since there is no SDP involved in the BYE
>>>>>>>> handshake) then finish the other leg.  The idea would be doing
>>>>>>>> something like this (not 100% real code, some pseudocode here)
>>>>>>>>
>>>>>>>>
>>>>>>>> protected void doBye(SipServletRequest req) throws
>>>>>>>> ServletException,IOException{
>>>>>>>>
>>>>>>>>     //Answer positively
>>>>>>>>     request.createResponse(200,"Have a nice day").send();
>>>>>>>>
>>>>>>>>     //Mark my dialog as finished
>>>>>>>>     request.getSession().setAttribute("FINISHED","OK");
>>>>>>>>
>>>>>>>>     //Get the other leg and finish it in case it is not  
>>>>>>>> finished
>>>>>>>>
>>>>>>>>     //Note how useful is to have in both SipSessions (that is,
>>>>>>>> both
>>>>>>>> legs) an attribute which refers the
>>>>>>>>     //other leg involved in the B2BUA transaction.
>>>>>>>>     SipSession counterPartLeg= (SipSession)
>>>>>>>> request.getSession.getAttribute("COUNTERPART_LEG");
>>>>>>>>     if (counterPartLeg.getAttribute("FINISHED")==null){
>>>>>>>>     counterPartLeg.createRequest("BYE").send();
>>>>>>>>     }
>>>>>>>> }
>>>>>>>>
>>>>>>>> Regards
>>>>>>>>
>>>>>>>> Gines
>>>>>>>>
>>>>>>>> El 05/03/2007, a las 14:36, tele escribió:
>>>>>>>>
>>>>>>>>> Hi Gines!
>>>>>>>>>
>>>>>>>>> It's almost clear to me how to do, this what i have done and
>>>>>>>>> it works.
>>>>>>>>>
>>>>>>>>> now i need last clarification how forward the 200 OK from BYE
>>>>>>>>> request, i
>>>>>>>>> cannot get it working.
>>>>>>>>> for forwarding the 200 ok from the BYE in the doBye request i
>>>>>>>>> save
>>>>>>>>> downstreamLeg.setAttribute("byereq", req) and then in the
>>>>>>>>> doResponse i
>>>>>>>>> get the bye request and create the response from it,
>>>>>>>>> something like this but i'm wrong.
>>>>>>>>>
>>>>>>>>> if (resp.getStatus() == 200 && resp.getMethod 
>>>>>>>>> ().equalsIgnoreCase
>>>>>>>>> ("BYE"))
>>>>>>>>> {
>>>>>>>>>                         SipServletRequest upstreamRequest =
>>>>>>>>> (SipServletRequest)upstreamLeg.getAttribute("byereq");
>>>>>>>>>                         SipServletResponse upstreamResponse =
>>>>>>>>> upstreamRequest.createResponse(resp.getStatus
>>>>>>>>> (),resp.getReasonPhrase
>>>>>>>>> ());
>>>>>>>>>                         //Copy the content from the downstream
>>>>>>>>> response
>>>>>>>>> to the upstream response
>>>>>>>>>                         if (resp.getContentType() != null) {
>>>>>>>>>
>>>>>>>>> upstreamResponse.setContent(resp.getRawContent(),
>>>>>>>>> resp.getContentType());
>>>>>>>>>                         }
>>>>>>>>>                         upstreamResponse.send();
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> this is what i have done for working ACK.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>   protected void doAck(SipServletRequest req) throws
>>>>>>>>> ServletException,
>>>>>>>>> IOException {
>>>>>>>>>         //Retrieve the upstream request to respond it
>>>>>>>>>         SipSession downstreamLeg =
>>>>>>>>> (SipSession)req.getSession().getApplicationSession
>>>>>>>>> ().getAttribute
>>>>>>>>> ("downstreamLeg");
>>>>>>>>>         SipServletResponse downstreamResponse =
>>>>>>>>> (SipServletResponse)
>>>>>>>>> downstreamLeg.getAttribute("200ok");
>>>>>>>>>         SipServletRequest ackRequest =
>>>>>>>>> downstreamResponse.createAck();
>>>>>>>>>         //Copy the content from the downstream response to the
>>>>>>>>> upstream
>>>>>>>>> response
>>>>>>>>>         if (req.getContentType() != null) {
>>>>>>>>>                 ackRequest.setContent(req.getRawContent(),
>>>>>>>>> req.getContentType());
>>>>>>>>>         }
>>>>>>>>>         ackRequest.send();
>>>>>>>>>    }
>>>>>>>>>
>>>>>>>>>    protected void doBye(SipServletRequest req) throws
>>>>>>>>> ServletException,
>>>>>>>>> IOException {
>>>>>>>>>         SipSession downstreamLeg =
>>>>>>>>> (SipSession)req.getSession().getApplicationSession
>>>>>>>>> ().getAttribute
>>>>>>>>> ("downstreamLeg");
>>>>>>>>>         SipServletRequest byeRequest =
>>>>>>>>> downstreamLeg.createRequest("BYE");
>>>>>>>>>         // Copy the content from the downstream response to  
>>>>>>>>> the
>>>>>>>>> upstream
>>>>>>>>> response
>>>>>>>>>         if (req.getContentType() != null) {
>>>>>>>>>                 byeRequest.setContent(req.getRawContent(),
>>>>>>>>> req.getContentType());
>>>>>>>>>         }
>>>>>>>>>         byeRequest.send();
>>>>>>>>>    }
>>>>>>>>>
>>>>>>>>>    protected void doResponse(SipServletResponse resp) throws
>>>>>>>>> ServletException, IOException {
>>>>>>>>>
>>>>>>>>>                 if (resp.getStatus() == 200 &&
>>>>>>>>> resp.getMethod().equalsIgnoreCase("INVITE")) {
>>>>>>>>>                         SipSession downstreamLeg =  
>>>>>>>>> (SipSession)
>>>>>>>>> resp.getSession().getApplicationSession().getAttribute
>>>>>>>>> ("downstreamLeg");
>>>>>>>>>                         downstreamLeg.setAttribute
>>>>>>>>> ("200ok",resp);
>>>>>>>>>                 }
>>>>>>>>>
>>>>>>>>>                 //Retrieve the upstream request to respond it
>>>>>>>>>                 SipSession upstreamLeg =
>>>>>>>>> (SipSession)resp.getSession().getApplicationSession
>>>>>>>>> ().getAttribute
>>>>>>>>> ("upstreamLeg");
>>>>>>>>>
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On Mon, 2007-03-05 at 00:29 +0100, Ginés Gómez wrote:
>>>>>>>>>> The problem is that you didn't implement the doACK method.
>>>>>>>>>> Implement
>>>>>>>>>> it following a similar technique as the one used in
>>>>>>>>>> doResponse. Save
>>>>>>>>>> the 200OK response in the downstream session so you can
>>>>>>>>>> retrieve it
>>>>>>>>>> when the ACK arrives from the upstream then generate ACK  
>>>>>>>>>> using
>>>>>>>>>> response.createACK() and copy the content using  
>>>>>>>>>> getContentType/
>>>>>>>>>> setContentType geContent/setContent if required
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Hope it helps
>>>>>>>>>>
>>>>>>>>>> Gines
>>>>>>>>>>
>>>>>>>>>>> Attached there is a .zip with all the log, trace and
>>>>>>>>>>> configuration.
>>>>>>>>>>>
>>>>>>>>>>> thanks for the support,
>>>>>>>>>>>
>>>>>>>>>>> :tele
>>>>>>>>>>> <wesip_test.zip>
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> Users mailing list
>>>>>>>>>>> Users at openser.org
>>>>>>>>>>> http://openser.org/cgi-bin/mailman/listinfo/users
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> _______________________________________________
>>>>>>>>> Users mailing list
>>>>>>>>> Users at openser.org
>>>>>>>>> http://openser.org/cgi-bin/mailman/listinfo/users
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> Users mailing list
>>>>>>> Users at openser.org
>>>>>>> http://openser.org/cgi-bin/mailman/listinfo/users
>>>>>>>
>>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> Users mailing list
>>>>> Users at openser.org
>>>>> http://openser.org/cgi-bin/mailman/listinfo/users
>>>>
>>>>
>>>> _______________________________________________
>>>> Users mailing list
>>>> Users at openser.org
>>>> http://openser.org/cgi-bin/mailman/listinfo/users
>>>
>>>
>>> _______________________________________________
>>> Users mailing list
>>> Users at openser.org
>>> http://openser.org/cgi-bin/mailman/listinfo/users
>>>
>>
>
>
> _______________________________________________
> Users mailing list
> Users at openser.org
> http://openser.org/cgi-bin/mailman/listinfo/users
>





More information about the Users mailing list