package sip;
import java.text.ParseException;
import java.util.HashSet;
import java.util.Set;
import javax.sip.DialogTerminatedEvent;
import javax.sip.InvalidArgumentException;
import javax.sip.RequestEvent;
import javax.sip.ResponseEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.ContactHeader;
import javax.sip.message.Response;
import org.apache.log4j.Logger;
public class UAS implements IMessageProcessor {
private static final boolean REGISTERED = true;
private static final boolean UNREGISTERED = false;
private UASObserver observer = null;
private SIPLayer sipLayer;
private static final Logger LOGGER = Logger.getLogger("UAS");
private boolean registered = UNREGISTERED;
private String registerCallId = "";
Set<String> dialogWaitingForAck = new HashSet<String>();
Set<String> dialogsActive = new HashSet<String>();
private ContactHeader contactHeader;
public UAS(SIPLayer sipLayer) {
this.sipLayer = sipLayer;
sipLayer.registerObserver(this);
contactHeader = sipLayer.getContactHeader();
}
public void registerAtProxy(String proxyAddress, int proxyPort) throws ParseException, InvalidArgumentException, SipException {
LOGGER.debug("registerAtProxy(" + proxyAddress + ", " + proxyPort + " )");
registerCallId = sipLayer.registerAtProxy(proxyAddress, proxyPort);
}
@Override
public void processDialogTerminated(DialogTerminatedEvent dte) {
LOGGER.debug("processDialogTerminated()");
String dialogId = dte.getDialog().getDialogId();
LOGGER.info("remove dialogId: " + dialogId + " from dialogsActive");
dialogsActive.remove(dialogId);
}
@Override
public void processOK(ResponseEvent responseEvent) {
LOGGER.debug("processOK()");
String receivedCallId = SIPLayer.getCallId(responseEvent);
if (registered == UNREGISTERED && registerCallId.equals(receivedCallId)) {
LOGGER.debug("Registered at proxy");
registered = REGISTERED;
} else {
LOGGER.debug("Unknown OK");
}
}
@Override
public void processTrying() {
LOGGER.debug("processTrying()");
}
@Override
public void processRinging() {
LOGGER.debug("processRinging()");
}
@Override
public void processInvite(RequestEvent requestEvent) {
LOGGER.debug("processInvite()");
Response response = null;
if (registered == UNREGISTERED) {
LOGGER.warn("UAS not registered at proxy, declining invite");
response = sipLayer.createResponse(Response.DECLINE, requestEvent.getRequest());
// TODO send response
} else if (registered == REGISTERED) {
String callId = SIPLayer.getCallId(requestEvent);
LOGGER.info("UAS sending OK to callId: " + callId);
try {
ServerTransaction serverTransaction = sipLayer.getNewServerTransaction(requestEvent.getRequest());
response = sipLayer.createResponse(Response.OK, requestEvent.getRequest());
response.addHeader(contactHeader);
LOGGER.trace("SENDEN: " + response.toString());
serverTransaction.sendResponse(response);
String dialogId = serverTransaction.getDialog().getDialogId();
dialogWaitingForAck.add(dialogId);
} catch (Exception e) {
LOGGER.warn("Response could not be send or build: ", e);
}
} else {
LOGGER.warn("Don't know how to handle invite");
response = sipLayer.createResponse(Response.NOT_IMPLEMENTED, requestEvent.getRequest());
// TODO send response
}
}
@Override
public void processBye(RequestEvent requestEvent) {
LOGGER.debug("processBye()");
String dialogId = requestEvent.getDialog().getDialogId();
// send OK
if (dialogsActive.contains(dialogId)) {
ServerTransaction serverTransaction = requestEvent.getServerTransaction();
Response response = sipLayer.createResponse(Response.OK, requestEvent.getRequest());
response.addHeader(contactHeader);
LOGGER.trace("SENDEN: " + response.toString());
try {
serverTransaction.sendResponse(response);
} catch (Exception e) {
LOGGER.warn("Response could not be send or build: ", e);
}
}
}
@Override
public void processAck(RequestEvent requestEvent) {
// if check dialog in dialogWaiting for ack
// yes: move dialog id to active dialog
// no: decline
String dialogId = requestEvent.getDialog().getDialogId();
LOGGER.trace("DialogId: " + dialogId);
if (dialogWaitingForAck.contains(dialogId)) {
LOGGER.info("Changing DialogId: " + dialogId + " to active");
dialogsActive.add(dialogId);
dialogWaitingForAck.remove(dialogId);
if(null != observer)
observer.notifyChangedActiveDialogs(dialogsActive);
} else {
LOGGER.warn("DialogId: " + dialogId + " is unknown in set of waiting dialogs");
Response response = sipLayer.createResponse(Response.DECLINE, requestEvent.getRequest());
// TODO send response
}
}
public int sessionCount() {
return dialogsActive.size();
}
public void setObserver(UASObserver observer) {
this.observer = observer;
}
}