/******************************************************* * This is a sip servlet.And it is not finished yet. * Current version is 1.0 * Author Norz * 03/06/2010 ********************************************************/ package myServlet; import javax.annotation.Resource; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.servlet.sip.Address; import javax.servlet.sip.Proxy; import javax.servlet.sip.SipErrorEvent; import javax.servlet.sip.SipErrorListener; import javax.servlet.sip.SipServlet; import javax.servlet.sip.SipFactory; import javax.servlet.sip.SipServletResponse; import javax.servlet.sip.SipSession; import java.io.IOException; import java.util.HashMap; import java.util.Properties; import javax.servlet.Servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.sip.SipServletRequest; @SuppressWarnings("unused") @javax.servlet.sip.annotation.SipServlet public class MyServlet extends SipServlet implements SipErrorListener,Servlet{ /** * Serial version UID. */ private static final long serialVersionUID = 1L; private static final String CONTACT_HEADER = "Contact"; private static final String SDPContent = "application/sdp"; private static final String HoldFlag = "a=sendonly"; private static final String ResFlag = "a=recvonly"; //call status private static final String BUSY = "busy"; private static final String HELD = "held"; private static final String WAITING = "waiting"; private static CallStatusContainer callsc; /** * The SIP Factory. Can be used to create URI and requests. */ @Resource private SipFactory sipFactory; public MyServlet(){ } /** * @inheritDoc */ @SuppressWarnings("unchecked") protected void doRegister(SipServletRequest req) throws ServletException, IOException { 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("registeredUserMap", 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); if( callsc.getSpecStatus(req.getFrom().toString()) != null) { callsc.removeSpecCall(req.getFrom().toString()); } } else { resp.setAddressHeader(CONTACT_HEADER, address); users.put(fromURI, address.getURI().toString()); } resp.send(); } /** * @inheritDoc */ protected void doSuccessResponse(SipServletResponse resp) throws ServletException, IOException { int response = SipServletResponse.SC_OK; if(resp.getStatus() == response) { String status = callsc.getSpecStatus(resp.getTo().toString()); if( status == HELD ) { resp.setContentLength(0); resp.send(); KeyStepOfCallWait(resp); } else { callsc.addCall(resp.getFrom().toString(), resp.getTo().toString(), BUSY); callsc.addCall(resp.getTo().toString(), resp.getFrom().toString(), BUSY); } } } /** * If receive a 182 queued,set the call to HELD,and change response to 183. * This mechanism focus on To.So when doSuccessResponse also focus on To * callsc.getSpecStatus(String To) */ protected void doProvisionalResponse(SipServletResponse resp) throws ServletException, IOException { int response = SipServletResponse.SC_SESSION_PROGRESS; if( resp.getStatus() == SipServletResponse.SC_CALL_QUEUED) { Call call = new Call(resp.getFrom().toString(),resp.getTo().toString()); call.setStatus(HELD); callsc.addCall(call.getFrom(),call.getTo(), HELD);//actually only To is HELD,and is needed. resp.setStatus(response); resp.send(); } } /** * Check the session of the request,if it's a INITIAL state,handle it as * a normal Invite,else if it's a CONFIRMED state,check if it contains * SDP message.And send 200 back. */ protected void doInvite(SipServletRequest req) throws ServletException, IOException { SipSession session = req.getSession(); if( session.getState().equals(SipSession.State.INITIAL)) //This is a normal Invite { Proxy proxy = req.getProxy(); proxy.setRecordRoute(true); proxy.setSupervised(true); proxy.proxyTo(req.getRequestURI()); } else if(session.getState().equals(SipSession.State.CONFIRMED))//This's sent by a CONFIRMED session,so it's a re-invite { if(req.getContentType().equalsIgnoreCase(SDPContent) && req.getContentLength() != 0) { //The request contains a SDP info String str = req.getContent().toString(); if(str.indexOf(HoldFlag) != -1 ) { //check if is a Call-Hold re-Invite int response = SipServletResponse.SC_OK; SipServletResponse resp = req.createResponse(response); resp.send(); callsc.addCall(req.getFrom().toString(), req.getTo().toString(), HELD); /* * Add SDP MRS to request */ Proxy proxy = req.getProxy(); proxy.setSupervised(true); proxy.setRecordRoute(true); proxy.proxyTo(req.getRequestURI()); } } } } /** * @inheritDoc */ protected void doAck(SipServletRequest req) throws ServletException, IOException { //TODO: Implement this method } /** * @inheritDoc */ protected void doBye(SipServletRequest req) throws ServletException, IOException { callsc.removeCall(req.getFrom().toString(), req.getTo().toString()); callsc.removeCall(req.getTo().toString(), req.getFrom().toString()); } /** * @inheritDoc */ protected void doErrorResponse(SipServletResponse resp) throws ServletException, IOException { callsc.removeCall(resp.getFrom().toString(), resp.getTo().toString()); callsc.removeCall(resp.getTo().toString(), resp.getFrom().toString()); } @Override public void noAckReceived(SipErrorEvent arg0) { // TODO Auto-generated method stub } @Override public void noPrackReceived(SipErrorEvent arg0) { // TODO Auto-generated method stub } public void KeyStepOfCallWait(SipServletResponse resp) throws IOException { Address To = (Address) resp.getTo().getURI(); Address From = (Address) resp.getFrom().getURI(); SipSession session = resp.getSession(); SipServletRequest request = session.createRequest("INVITE"); request.setAddressHeader("From", From); request.setAddressHeader("To", To); request.send(); request.setAddressHeader("To", From); request.setAddressHeader("From", To); request.send(); } }