The CallSipServlet SIP servlet connects registered SIP users to one another, allowing users to place calls to one another. There are 5 main SIP methods in CallSipServlet: doSuccessResponse, sendInviteToClient, sendAckToClient, sendAckToServer, and sent200OKToClient.
CallSipServlet is annotated at the class-level with a @SipServlet and @SipListener annotation.
@javax.servlet.sip.annotation.SipServlet
@SipListener
public class CallSipServlet extends SipServlet implements SipSessionListener {
...
}
The doSuccessResponse method connects a call between two registered users. When the first user Alice initiates a call to the second user Bob, first Alice's phone rings. If Alice answers her phone, a SIP OK message is sent. At that point, Bob's address is extracted from the request, a SIP INVITE message is sent to Bob's address by calling the sendInviteToClient private method, and Bob's phone rings. If Bob answers the phone, a SIP OK message is sent. The two SIP sessions, from Alice and Bob respectively, are linked, and a SIP ACK message is sent to both user's phones by calling the sendAckToClient and sendAckToServer private methods. Alice and Bob are now connected and can have a conversation. When the call is terminated, a BYE message is sent from the server, and the send200OKToClient private method is called.
@Override
protected void doSuccessResponse(SipServletResponse resp)
throws ServletException, IOException {
logger.info("Received a response.\n" + resp);
if (resp.getMethod().equals("INVITE")) {
List<SipSession> sipSessions = getSipSessions(resp.getApplicationSession());
if (sipSessions.size() == 1) {
sipSessions.get(0).setAttribute("ACK", resp.createAck());
sendInviteToClient(resp);
} else { // 200 OK from Client
sendAckToClient(resp);
sendAckToServer(resp);
}
} else if (resp.getMethod().equals("BYE")) {
send200OKToClient(resp);
}
}
private void sendInviteToClient(SipServletResponse serverResp)
throws ServletException, IOException {
SipServletRequest serverReq = serverResp.getRequest();
B2buaHelper b2buaHelper = serverReq.getB2buaHelper();
// Swap To & From headers.
Map<String, List<String>> headerMap = new HashMap<String, List<String>>();
List<String> from = new ArrayList<String>();
from.add(serverResp.getHeader("From"));
headerMap.put("To", from);
List<String> to = new ArrayList<String>();
to.add(serverResp.getHeader("To"));
headerMap.put("From", to);
SipServletRequest clientRequest = b2buaHelper
.createRequest(serverReq, true, headerMap);
clientRequest.setRequestURI(clientRequest.getAddressHeader("To").getURI());
if (serverResp.getContent() != null) { // set sdp1
clientRequest.setContent(serverResp.getContent(),
serverResp.getContentType());
}
logger.info("Sending INVITE to client.\n" + clientRequest);
clientRequest.send();
}
private void sendAckToClient(SipServletResponse clientResp)
throws ServletException, IOException {
SipServletRequest ack = clientResp.createAck();
logger.info("Sending ACK to client.\n" + ack);
ack.send();
}
private void sendAckToServer(SipServletResponse clientResp)
throws ServletException, IOException {
B2buaHelper b2buaHelper = clientResp.getRequest().getB2buaHelper();
SipSession clientSession = clientResp.getSession();
SipSession serverSession = b2buaHelper.getLinkedSession(clientSession);
SipServletRequest ack = (SipServletRequest) serverSession.getAttribute("ACK");
serverSession.removeAttribute("ACK");
if (clientResp.getContent() != null) { // set sdp2
ack.setContent(clientResp.getContent(), clientResp.getContentType());
}
logger.info("Sending ACK to server.\n" + ack);
ack.send();
}
protected void doBye(SipServletRequest request)
throws ServletException, IOException
{
logger.info("Got bye");
SipSession session = request.getSession();
// end the linked call
SipSession linkedSession = (SipSession) session.getAttribute("LinkedSession");
if (linkedSession != null) {
// create a BYE request to the linked session
SipServletRequest bye = linkedSession.createRequest("BYE");
logger.info("Sending bye to " + linkedSession.getRemoteParty());
// send the BYE request
bye.send();
}
// send an OK for the BYE
SipServletResponse ok = request.createResponse(SipServletResponse.SC_OK);
ok.send();
}
There are three SIP session listener methods implemented in CallSipServlet, from the SipSessionListener interface: sessionCreated, sessionDestroyed, and sessionReadyToInvalidate. In CallSipServlet, the methods simply log the events.
public void sessionCreated(SipSessionEvent sse) {
logger.info("Session created");
}
public void sessionDestroyed(SipSessionEvent sse) {
logger.info("Session destroyed");
}
public void sessionReadyToInvalidate(SipSessionEvent sse) {
logger.info("Session ready to be invalidated");
}