/*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.mobicents.servlet.sip.monitoring;
import java.io.IOException;
import java.util.HashMap;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.sip.Address;
import javax.servlet.sip.AuthInfo;
import javax.servlet.sip.SipFactory;
import javax.servlet.sip.SipServlet;
import javax.servlet.sip.SipServletRequest;
import javax.servlet.sip.SipServletResponse;
import javax.servlet.sip.SipSession;
import org.apache.log4j.Logger;
import org.mobicents.mscontrol.MsConnection;
import org.mobicents.mscontrol.MsConnectionState;
import org.mobicents.mscontrol.MsLink;
import org.mobicents.servlet.sip.monitoring.util.DTMFListener;
import org.mobicents.servlet.sip.monitoring.util.DTMFUtils;
import org.mobicents.servlet.sip.monitoring.util.MediaLinkListener;
public class PhoneCallSipServlet extends SipServlet {
private static final long serialVersionUID = 1L;
private static Logger logger = Logger.getLogger(PhoneCallSipServlet.class);
private static final String CONTACT_HEADER = "Contact";
private static final String INVITE = "INVITE";
public PhoneCallSipServlet() {
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
logger.info("the PhoneCallSipServlet has been started");
}
@Override
protected void doInvite(SipServletRequest req) throws ServletException,
IOException {
logger.info("Monitoring App don't handle INVITE yet. Here's the one we got : " + req.toString());
}
@Override
protected void doOptions(SipServletRequest req) throws ServletException,
IOException {
logger.info("Got : " + req.toString());
req.createResponse(SipServletResponse.SC_OK).send();
}
@Override
protected void doProvisionalResponse(SipServletResponse sipServletResponse)
throws ServletException, IOException {
logger.info("Got : " + sipServletResponse.getStatus() + " "
+ sipServletResponse.getMethod());
int status = sipServletResponse.getStatus();
if (status == SipServletResponse.SC_SESSION_PROGRESS &&
INVITE.equalsIgnoreCase(sipServletResponse.getMethod())) {
//creates the connection
Object sdpObj = sipServletResponse.getContent();
byte[] sdpBytes = (byte[]) sdpObj;
String sdp = new String(sdpBytes);
logger.info("Creating the end to end media connection");
sipServletResponse.getSession().setAttribute("playAnnouncement", Boolean.FALSE);
sipServletResponse.getSession().setAttribute("audioFilePath", (String)getServletContext().getAttribute("audioFilePath"));
MsConnection connection = (MsConnection)sipServletResponse.getSession().getAttribute("connection");
connection.modify("$", sdp);
}
}
@Override
protected void doSuccessResponse(SipServletResponse sipServletResponse)
throws ServletException, IOException {
logger.info("Got : " + sipServletResponse.getStatus() + " "
+ sipServletResponse.getMethod());
int status = sipServletResponse.getStatus();
if (status == SipServletResponse.SC_OK && "INVITE".equalsIgnoreCase(sipServletResponse.getMethod())) {
// send ack
SipServletRequest ackRequest = sipServletResponse.createAck();
ackRequest.send();
//creates the connection
Object sdpObj = sipServletResponse.getContent();
byte[] sdpBytes = (byte[]) sdpObj;
String sdp = new String(sdpBytes);
MsConnection connection = (MsConnection)sipServletResponse.getSession().getAttribute("connection");
if(!connection.getState().equals(MsConnectionState.OPEN)) {
logger.info("Creating the end to end media connection");
sipServletResponse.getSession().setAttribute("playAnnouncement", Boolean.TRUE);
connection.modify("$", sdp);
} else {
logger.info("Not Creating the end to end media connection, connection already opened");
MediaLinkListener.playAnnouncement(
connection,
(MsLink)sipServletResponse.getSession().getAttribute("link"),
sipServletResponse.getSession(),
(String)sipServletResponse.getSession().getAttribute("fileName"),
(String)sipServletResponse.getSession().getAttribute("alertId"),
(String)getServletContext().getAttribute("alert.feedback.url"));
}
}
}
@Override
protected void doErrorResponse(SipServletResponse response)
throws ServletException, IOException {
logger.info("Got response: " + response);
SipFactory sipFactory = (SipFactory) getServletContext().getAttribute(SIP_FACTORY);
if(response.getStatus() == SipServletResponse.SC_UNAUTHORIZED ||
response.getStatus() == SipServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED) {
// Avoid re-sending if the auth repeatedly fails.
if(!"true".equals(response.getSession().getAttribute("FirstResponseRecieved")))
{
SipSession sipSession = response.getSession();
sipSession.setAttribute("FirstResponseRecieved", "true");
AuthInfo authInfo = sipFactory.createAuthInfo();
authInfo.addAuthInfo(
response.getStatus(),
response.getChallengeRealms().next(),
getServletContext().getInitParameter("caller.sip"),
getServletContext().getInitParameter("caller.password"));
SipServletRequest challengeRequest = response.getSession().createRequest(
response.getRequest().getMethod());
challengeRequest.addAuthHeader(response, authInfo);
MsConnection connection = (MsConnection)
sipSession.getAttribute("connection");
if(connection != null) {
String sdp = connection.getLocalDescriptor();
try {
challengeRequest.setContentLength(sdp.length());
challengeRequest.setContent(sdp.getBytes(), "application/sdp");
} catch (IOException e) {
logger.error("An unexpected exception occured while sending the request", e);
}
}
logger.info("sending challenge request " + challengeRequest);
challengeRequest.send();
}
} else {
super.doErrorResponse(response);
}
}
@Override
protected void doInfo(SipServletRequest request) throws ServletException,
IOException {
//sending OK
SipServletResponse ok = request.createResponse(SipServletResponse.SC_OK);
ok.send();
//Getting the message content
String messageContent = new String( (byte[]) request.getContent());
logger.info("got INFO request with following content " + messageContent);
int signalIndex = messageContent.indexOf("Signal=");
//Playing file only if the DTMF session has been started
if(DTMFListener.DTMF_SESSION_STARTED == (Integer) request.getSession().getAttribute("DTMFSession")) {
logger.info("DTMF session in started state, parsing message content");
if(messageContent != null && messageContent.length() > 0 && signalIndex != -1) {
String signal = messageContent.substring("Signal=".length(),"Signal=".length()+1).trim();
logger.info("Signal received " + signal );
DTMFUtils.answerBack((String)request.getSession().getAttribute("alertId"), signal, (String)getServletContext().getAttribute("alert.feedback.url"));
}
} else {
logger.info("DTMF session in stopped state, not parsing message content");
}
}
@Override
protected void doBye(SipServletRequest request) throws ServletException,
IOException {
logger.info("Got bye " + request);
MsConnection connection = (MsConnection)request.getSession().getAttribute("connection");
MsLink link = (MsLink)request.getSession().getAttribute("link");
SipServletResponse ok = request
.createResponse(SipServletResponse.SC_OK);
ok.send();
if(connection != null) {
connection.release();
} else {
logger.info("connection not created");
}
if(link != null) {
link.release();
} else {
logger.info("link not created");
}
}
protected void doRegister(SipServletRequest req) throws ServletException, IOException {
logger.info("Received register request: " + req.getTo());
int response = SipServletResponse.SC_OK;
SipServletResponse resp = req.createResponse(response);
HashMap<String, String> users = (HashMap<String, String>) getServletContext().getAttribute("registeredUsersMap");
if(users == null) users = new HashMap<String, String>();
getServletContext().setAttribute("registeredUsersMap", users);
Address address = req.getAddressHeader(CONTACT_HEADER);
String fromURI = req.getFrom().getURI().toString();
int expires = address.getExpires();
if(expires < 0) {
expires = req.getExpires();
}
if(expires == 0) {
users.remove(fromURI);
logger.info("User " + fromURI + " unregistered");
} else {
resp.setAddressHeader(CONTACT_HEADER, address);
users.put(fromURI, address.getURI().toString());
logger.info("User " + fromURI +
" registered with an Expire time of " + expires);
}
resp.send();
}
}