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@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Hi ,
can you double check that you do actually save the BYE request ? I couldn´t see the code in the doBye method.
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(); }
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@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Hi,
yes the correct way, respond to the BYE request with a 200 OK in the correct call-leg and than generate the BYE request in the other call-leg for close the other dialog.
I'm not fully understand what you means in your pseudo-code It's not clear to me how to identified the correct call-leg where to send the BYE message. The problem is that if the BYE come from the called the legs al terminated correctly, but if come from the caller the BYE request that i create is not correct, the call-id is of the request recived.
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@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Hi ,
I'm not fully understand what you means in your pseudo-code It's not clear to me how to identified the correct call-leg where to send the BYE message. The problem is that if the BYE come from the called the legs al terminated correctly, but if come from the caller the BYE request that i create is not correct, the call-id is of the request recived.
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@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
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@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
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@openser.org > http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
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@openser.org >> http://openser.org/cgi-bin/mailman/listinfo/users >
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Hi Teles,
delicate issue :-) Basically, what the specification is telling us is that you are not expected to answer a CANCEL request in the doCancel method. The container manages the CANCEL and INVITE transactions for you generating the appropiate responses and cancelling branches if needed according to UAS or proxy roles played by the application. You receive the CANCEL request in the doCancel method for sake of notification to the application only.
Since you are not doing proxy, but B2BUA, from the point of view of the container, the upstream leg (which is a UAS) and the downstream (which is a UAC) are completely separated and only linked at an application level, that means that is up to the application to manage the upstream CANCEL. You have to proceed in three different ways depending on the transaction state:
A) You have answered to the upstream INVITE request with a final positive final response:
- The container will automatically send a 200OK to the CANCEL - You don't receive the CANCEL request in the doCANCEL since the transaction is not cancelled - The upstream sends a BYE request when it receives the 200OK (since it realizes that the transaction couldn't be cancelled) - You manage the BYE request as usual
B) You have answered to the upstream INVITE request with a non positive final response (i.e. 4XX):
- The container will automatically send a 200OK to the CANCEL - You don't receive the CANCEL request in the doCANCEL since the transaction is not cancelled - The downstream dialog is not supposed to be stablished (if it was you application wouldn't have sent an error response to the upstream, would it? ) so no need to care about it
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@openser.org >>> http://openser.org/cgi-bin/mailman/listinfo/users >> > > > _______________________________________________ > Users mailing list > Users@openser.org > http://openser.org/cgi-bin/mailman/listinfo/users >
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
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@openser.org >>>> http://openser.org/cgi-bin/mailman/listinfo/users >>> >> >> >> _______________________________________________ >> Users mailing list >> Users@openser.org >> http://openser.org/cgi-bin/mailman/listinfo/users >> >
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
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@openser.org >>>>> http://openser.org/cgi-bin/mailman/listinfo/users >>>> >>> >>> >>> _______________________________________________ >>> Users mailing list >>> Users@openser.org >>> http://openser.org/cgi-bin/mailman/listinfo/users >>> >> > > > _______________________________________________ > Users mailing list > Users@openser.org > http://openser.org/cgi-bin/mailman/listinfo/users >
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Hi gines,
Ops i don't remember why i had force the ruri, probably a "no route" exception. anyway the code only cancel the downstreamleg. this one cancel the 'other leg':
protected void doCancel(SipServletRequest req) throws ServletException, IOException { req.getSession().setAttribute("FINISHED","OK"); try { SipSession counterPartLeg = (SipSession) req.getSession().getAttribute("COUNTERPART_LEG"); SipServletRequest otherInvite = (SipServletRequest) counterPartLeg.getAttribute("initialRequest"); if (counterPartLeg.getAttribute("FINISHED")==null) { otherInvite.createCancel().send(); } } catch (IllegalStateException e) { SipSession counterPartLeg = (SipSession)req.getSession().getAttribute("COUNTERPART_LEG"); if (counterPartLeg.getAttribute("FINISHED")==null) { counterPartLeg.createRequest("BYE").send(); } } }
i can see WeSIP try to send the correct CANCEL to the other leg. this is the scenario:
WeSIP | UA ---> GW ---> PSTN
WeSIP - 192.168.1.10 GW - 192.168.1.11
Upstream call-id: 905071693-18135@GW Downstream call-id: 1111905071693-18135@GW
other info, i'm using SPIRAL 'true', so in my openser.cfg i have:
if(is_present_hf("X-WeSIP-SPIRAL")){ t_relay(); }else{ as_relay_t("app_server_one"); }
if you look on the wesip.log attached you can see WeSIP send the CANCEL in the correct leg but never reach the GW. I can see the same CANCEL come back to the WeSIP.
maybe the problem could be the related to the X-WeSIP-SPIRAL header, i can see the CANCEL retrasmission in openser.log.
attached here openser.log and wesip.log
regards
:tele
On Thu, 2007-03-08 at 23:24 +0100, Ginés Gómez wrote:
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@openser.org >>>>>> http://openser.org/cgi-bin/mailman/listinfo/users >>>>> >>>> >>>> >>>> _______________________________________________ >>>> Users mailing list >>>> Users@openser.org >>>> http://openser.org/cgi-bin/mailman/listinfo/users >>>> >>> >> >> >> _______________________________________________ >> Users mailing list >> Users@openser.org >> http://openser.org/cgi-bin/mailman/listinfo/users >> >
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users
Users mailing list Users@openser.org http://openser.org/cgi-bin/mailman/listinfo/users