package org.mobicents.slee.sipevent.server.subscription.sip;
import gov.nist.javax.sip.Utils;
import javax.persistence.EntityManager;
import javax.sip.Dialog;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.address.Address;
import javax.sip.header.ContentTypeHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.ToHeader;
import javax.sip.message.Response;
import javax.slee.ActivityContextInterface;
import javax.slee.SbbLocalObject;
import net.java.slee.resource.sip.DialogActivity;
import org.apache.log4j.Logger;
import org.mobicents.slee.sipevent.server.subscription.ImplementedSubscriptionControlSbbLocalObject;
import org.mobicents.slee.sipevent.server.subscription.SubscriptionControlSbb;
import org.mobicents.slee.sipevent.server.subscription.pojo.Subscription;
import org.mobicents.slee.sipevent.server.subscription.pojo.SubscriptionKey;
/**
* Handles the creation of a new SIP subscription
*
* @author martins
*
*/
public class NewSipSubscriptionHandler {
private static Logger logger = Logger
.getLogger(SubscriptionControlSbb.class);
private SipSubscriptionHandler sipSubscriptionHandler;
public NewSipSubscriptionHandler(
SipSubscriptionHandler sipSubscriptionHandler) {
this.sipSubscriptionHandler = sipSubscriptionHandler;
}
/**
* Starts the process of handling a new sip subscription
*
* @param event
* @param aci
* @param eventPackage
* @param eventId
* @param expires
* @param entityManager
* @param childSbb
*/
public void newSipSubscription(RequestEvent event,
ActivityContextInterface aci, String eventPackage, String eventId,
int expires, EntityManager entityManager,
ImplementedSubscriptionControlSbbLocalObject childSbb) {
// get subscription data from request
Address fromAddress = ((FromHeader) event.getRequest().getHeader(
FromHeader.NAME)).getAddress();
String subscriber = fromAddress.getURI().toString();
String subscriberDisplayName = fromAddress.getDisplayName();
String notifier = event.getRequest().getRequestURI().toString();
// get content
String content = null;
String contentType = null;
String contentSubtype = null;
ContentTypeHeader contentTypeHeader = (ContentTypeHeader) event
.getRequest().getHeader(ContentTypeHeader.NAME);
if (contentTypeHeader != null) {
contentType = contentTypeHeader.getContentType();
contentSubtype = contentTypeHeader.getContentSubType();
content = new String(event.getRequest().getRawContent());
}
// create dialog if does not exists
Dialog dialog = event.getDialog();
if (dialog == null) {
try {
dialog = sipSubscriptionHandler.sbb.getSipProvider()
.getNewDialog(event.getServerTransaction());
} catch (Exception e) {
logger.error("Can't create dialog", e);
// cleanup
try {
Response response = sipSubscriptionHandler.sbb
.getMessageFactory().createResponse(
Response.SERVER_INTERNAL_ERROR,
event.getRequest());
response = sipSubscriptionHandler
.addContactHeader(response);
event.getServerTransaction().sendResponse(response);
if (logger.isDebugEnabled()) {
logger.debug("Response sent:\n" + response.toString());
}
} catch (Exception f) {
logger.error("Can't send RESPONSE", f);
}
return;
}
}
SubscriptionKey key = new SubscriptionKey(dialog.getCallId()
.getCallId(), dialog.getRemoteTag(), eventPackage, eventId);
if (sipSubscriptionHandler.sbb.getConfiguration().getEventListSupportOn()) {
// we need to find out if the notifier is a resource list
int rlsResponse = sipSubscriptionHandler.sbb.getEventListControlChildSbb().validateSubscribeRequest(subscriber, notifier,eventPackage,event);
switch (rlsResponse) {
case Response.NOT_FOUND:
// the notifier is not a resource list, proceed with normal authorization means
authorizeNewSipSubscription(event, aci, subscriber, subscriberDisplayName, notifier, key, expires, content, contentType, contentSubtype, false, entityManager, childSbb);
break;
case Response.OK:
// the notifier is a resource list
authorizeNewSipSubscription(event, aci, subscriber, subscriberDisplayName, notifier, key, expires, content, contentType, contentSubtype, true, entityManager, childSbb);
break;
default:
// the rls request validation returned an error
try {
Response response = sipSubscriptionHandler.sbb.getMessageFactory().createResponse(rlsResponse, event.getRequest());
response = sipSubscriptionHandler
.addContactHeader(response);
response.addHeader(sipSubscriptionHandler.sbb.getHeaderFactory().createRequireHeader("eventlist"));
event.getServerTransaction().sendResponse(response);
if (logger.isDebugEnabled()) {
logger.debug("Response sent:\n" + response.toString());
}
} catch (Exception f) {
logger.error("Can't send RESPONSE", f);
}
return;
}
}
else {
authorizeNewSipSubscription(event, aci, subscriber, subscriberDisplayName, notifier, key, expires, content, contentType, contentSubtype, false, entityManager, childSbb);
}
}
/**
* Requests authorization for the new sip subscription.
*
* @param event
* @param aci
* @param subscriber
* @param subscriberDisplayName
* @param notifier
* @param key
* @param expires
* @param content
* @param contentType
* @param contentSubtype
* @param entityManager
* @param childSbb
*/
public void authorizeNewSipSubscription(RequestEvent event,
ActivityContextInterface aci, String subscriber, String subscriberDisplayName, String notifier, SubscriptionKey key, int expires, String content,
String contentType, String contentSubtype, boolean eventList, EntityManager entityManager,
ImplementedSubscriptionControlSbbLocalObject childSbb) {
// ask authorization
if (key.getEventPackage().endsWith(".winfo")) {
// winfo package, only accept subscriptions when subscriber and
// notifier are the same
newSipSubscriptionAuthorization(event.getServerTransaction(), aci,
subscriber, subscriberDisplayName, notifier, key,
expires, (subscriber.equals(notifier) ? Response.OK
: Response.FORBIDDEN), eventList, entityManager, childSbb);
} else {
childSbb.isSubscriberAuthorized(subscriber, subscriberDisplayName, notifier, key, expires, content,
contentType, contentSubtype, eventList, event.getServerTransaction());
}
}
/**
* Used by {@link ImplementedSubscriptionControlSbbLocalObject} to provide
* the authorization to a new sip subscription request.
*
* @param event
* @param subscriber
* @param notifier
* @param subscriptionKey
* @param expires
* @param responseCode
* @param entityManager
* @param childSbb
*/
public void newSipSubscriptionAuthorization(
ServerTransaction serverTransaction,
ActivityContextInterface serverTransactionACI, String subscriber,
String subscriberDisplayName, String notifier, SubscriptionKey key,
int expires, int responseCode, boolean eventList, EntityManager entityManager,
ImplementedSubscriptionControlSbbLocalObject childSbb) {
Dialog dialog = serverTransaction.getDialog();
ActivityContextInterface dialogAci = null;
// send response
try {
Response response = sipSubscriptionHandler.sbb.getMessageFactory()
.createResponse(responseCode,
serverTransaction.getRequest());
if (responseCode == Response.ACCEPTED
|| responseCode == Response.OK) {
ToHeader responseToHeader = (ToHeader) response
.getHeader(ToHeader.NAME);
responseToHeader.setTag(Utils.getInstance().generateTag());
// attach to dialog
SbbLocalObject sbbLocalObject = sipSubscriptionHandler.sbb
.getSbbContext().getSbbLocalObject();
dialogAci = sipSubscriptionHandler.sbb
.getSipActivityContextInterfaceFactory()
.getActivityContextInterface((DialogActivity) dialog);
dialogAci.attach(sbbLocalObject);
if (serverTransactionACI != null) {
serverTransactionACI.detach(sbbLocalObject);
}
// finish and send response
response = sipSubscriptionHandler.addContactHeader(response);
response.addHeader(sipSubscriptionHandler.sbb
.getHeaderFactory().createExpiresHeader(expires));
serverTransaction.sendResponse(response);
if (logger.isDebugEnabled()) {
logger.debug("Response sent:\n" + response.toString());
}
} else {
response = sipSubscriptionHandler.addContactHeader(response);
serverTransaction.sendResponse(response);
if (logger.isInfoEnabled()) {
logger.info("Subscription: subscriber=" + subscriber
+ ",notifier=" + notifier + ",eventPackage="
+ key.getEventPackage() + " not authorized ("
+ responseCode + ")");
}
if (logger.isDebugEnabled()) {
logger.debug("Response sent:\n" + response.toString());
}
return;
}
} catch (Exception e) {
logger.error("Can't send new subscription request's reponse", e);
// cleanup
try {
Response response = sipSubscriptionHandler.sbb
.getMessageFactory().createResponse(
Response.SERVER_INTERNAL_ERROR,
serverTransaction.getRequest());
response = sipSubscriptionHandler.addContactHeader(response);
serverTransaction.sendResponse(response);
if (logger.isDebugEnabled()) {
logger.debug("Response sent:\n" + response.toString());
}
} catch (Exception f) {
logger.error("Can't send RESPONSE", f);
}
return;
}
// create subscription, initial status depends on authorization
Subscription.Status initialStatus = responseCode == Response.ACCEPTED ? Subscription.Status.pending
: Subscription.Status.active;
Subscription subscription = new Subscription(key, subscriber, notifier,
initialStatus, subscriberDisplayName, expires, eventList);
if (!eventList || (responseCode == Response.ACCEPTED)) {
// single resource or pending subscription (no notify content), notify subscriber
try {
sipSubscriptionHandler.getSipSubscriberNotificationHandler()
.createAndSendNotify(entityManager, subscription, dialog,
childSbb);
} catch (Exception e) {
logger.error("failed to notify subscriber", e);
}
}
// notify winfo subscribers
sipSubscriptionHandler.sbb
.getWInfoSubscriptionHandler()
.notifyWinfoSubscriptions(entityManager, subscription, childSbb);
// bind name for dialog aci
try {
sipSubscriptionHandler.sbb.getActivityContextNamingfacility().bind(
dialogAci, key.toString());
} catch (Exception e) {
logger.error("failed to bind a name to dialog's aci", e);
}
// set new timer
sipSubscriptionHandler.sbb.setSubscriptionTimerAndPersistSubscription(
entityManager, subscription, expires + 1, dialogAci);
if (eventList && (responseCode == Response.OK)) {
// it's a resource list and active subscription, delegate to the event list control for further process of the new subscription
if (!sipSubscriptionHandler.sbb.getEventListControlChildSbb().createSubscription(subscription)) {
// sip subscription
sipSubscriptionHandler
.getRemoveSipSubscriptionHandler()
.removeSipSubscription(dialogAci, subscription, entityManager, childSbb);
}
}
if (logger.isInfoEnabled()) {
logger.info("Created " + subscription);
}
}
}