package org.mobicents.slee.examples.wakeup; import java.util.ArrayList; import java.util.Iterator; import java.util.Map; import javax.naming.Context; import javax.naming.InitialContext; import javax.sip.ClientTransaction; import javax.sip.ServerTransaction; import javax.sip.address.Address; import javax.sip.address.AddressFactory; import javax.sip.address.SipURI; import javax.sip.address.URI; import javax.sip.header.ContactHeader; import javax.sip.header.ContentTypeHeader; import javax.sip.header.FromHeader; import javax.sip.header.Header; import javax.sip.header.HeaderFactory; import javax.sip.header.MaxForwardsHeader; import javax.sip.header.ToHeader; import javax.sip.header.ViaHeader; import javax.sip.message.MessageFactory; import javax.sip.message.Request; import javax.sip.message.Response; import javax.slee.ActivityContextInterface; import javax.slee.ChildRelation; import javax.slee.RolledBackContext; import javax.slee.SbbContext; import javax.slee.facilities.TimerEvent; import javax.slee.facilities.TimerFacility; import javax.slee.facilities.TimerOptions; import javax.slee.nullactivity.NullActivity; import javax.slee.nullactivity.NullActivityContextInterfaceFactory; import javax.slee.nullactivity.NullActivityFactory; import net.java.slee.resource.sip.SleeSipProvider; import org.apache.log4j.Logger; import org.mobicents.slee.services.sip.common.SipSendErrorResponseException; import org.mobicents.slee.services.sip.location.LocationSbbLocalObject; import org.mobicents.slee.services.sip.location.LocationServiceException; import org.mobicents.slee.services.sip.location.RegistrationBinding; public abstract class WakeUpSbb implements javax.slee.Sbb { /** * Child relation to the location service * @return */ public abstract ChildRelation getLocationChildRelation(); /** * creates (if not created yet) and retrieves the child sbb instance for the * location service * * @return */ public LocationSbbLocalObject getLocationChildSbb() { ChildRelation childRelation = getLocationChildRelation(); Iterator childRelationIterator = childRelation.iterator(); if (childRelationIterator.hasNext()) { return (LocationSbbLocalObject) childRelationIterator.next(); } else { try { return (LocationSbbLocalObject) childRelation.create(); } catch (Exception e) { logger.error( "failed to create child sbb", e); return null; } } } /** * Event handler for the SIP MESSAGE from the UA * @param event * @param aci */ public void onMessageEvent(javax.sip.RequestEvent event, ActivityContextInterface aci) { Request request = event.getRequest(); try { // Notifiy the client that we received the SIP MESSAGE request ServerTransaction st = (ServerTransaction) aci.getActivity(); Response response = messageFactory.createResponse(Response.OK, request); st.sendResponse(response); // PARSING THE MESSAGE BODY should be *WAKE UP IN <timer value in // seconds>s! MSG: <msg to send back to UA>!* String body = new String(request.getRawContent()); int i = body.indexOf("WAKE UP IN "); int j = body.indexOf("s! MSG: ",i+11); int k = body.indexOf("!",j+8); if (i >-1 && j>-1 && k >-1) { String timerValue = body.substring(i+11,j); int timer = Integer.parseInt(timerValue); String bodyMessage = body.substring(j+8,k); // CREATE A NEW NULL ACTIVITIY NullActivity timerBus = this.nullActivityFactory.createNullActivity(); // ATTACH ITSELF TO THE NULL ACTIVITY // BY USING THE ACTIVITY CONTEXT INTERFACE ActivityContextInterface timerBusACI = this.nullACIFactory.getActivityContextInterface(timerBus); timerBusACI.attach(sbbContext.getSbbLocalObject()); // SETTING VALUES ON THE ACTIVITY CONTEXT // USING THE SBB CUSTOM ACI WakeUpSbbActivityContextInterface myViewOfTimerBusACI = this.asSbbActivityContextInterface(timerBusACI); myViewOfTimerBusACI.setBody(bodyMessage); // The From field of each SIP MESSAGE has the UA Address of Record (logical address), // which can be mapped to a current physical contact address. The mapping is provided by the LocationService, // which works together with the SIP Registrar service. FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME); logger.info("Received a valid message from " + fromHeader.getAddress()+" requesting a reply containing '"+bodyMessage+"' after "+timerValue+"s"); URI contactURI = findLocalTarget(fromHeader.getAddress().getURI(),getLocationChildSbb()); Address contactAddress = addressFactory.createAddress(contactURI); ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress); myViewOfTimerBusACI.setContact(contactHeader); // SETTING THE TIMER BY USING THE VALUE // IN THE SIP MESSAGE BODY TimerOptions options = new TimerOptions(); options.setPersistent(true); this.timerFacility.setTimer(timerBusACI, null, System.currentTimeMillis()+timer*1000, options); } else { logger.warn("Ignoring invalid msg "+body); } } catch (Exception e) { logger.error( "Exception while processing MESSAGE: ", e); } } /** * Event handler from the timer event, which signals that a message must be * sent back to the UA * * @param event * @param aci */ public void onTimerEvent(TimerEvent event, ActivityContextInterface aci) { // DETACHING SO NULL ACI IS CLAIMED WHEN THE TRANSACTION ENDS aci.detach(sbbContext.getSbbLocalObject()); // RETRIEVING STORED VALUE FROM THE ACTIVITY CONTEXT INTERFACE WakeUpSbbActivityContextInterface myViewOfACI = this.asSbbActivityContextInterface(aci); // GET DATA FROM ACI Header contact = myViewOfACI.getContact(); String body = myViewOfACI.getBody(); // SENDING BACK THE WAKE UP CALL sendWakeUpCall(contact, body); } /* * constructs and sends a SIP MESSAGE back to the UA */ private void sendWakeUpCall(Header toContact, String body) { String strContact = toContact.toString(); int beginIndex = strContact.indexOf('<'); int endIndex = strContact.indexOf('>'); String toAddressStr = strContact.substring(beginIndex+1, endIndex); try { SipURI fromAddress = addressFactory.createSipURI("wakeup", System.getProperty("bind.address","127.0.0.1")); javax.sip.address.Address fromNameAddress = addressFactory.createAddress(fromAddress); fromNameAddress.setDisplayName("WakeUp"); FromHeader fromHeader = headerFactory.createFromHeader(fromNameAddress, "12345SomeTagID6789"); javax.sip.address.Address toNameAddress = addressFactory.createAddress(toAddressStr); toNameAddress.setDisplayName("Some Sleepy User"); ToHeader toHeader = headerFactory.createToHeader(toNameAddress, null); ArrayList viaHeaders = new ArrayList(); ViaHeader viaHeader = headerFactory.createViaHeader( provider.getListeningPoints()[0].getIPAddress(), provider.getListeningPoints()[0].getPort(), provider.getListeningPoints()[0].getTransport(), null); // add via headers viaHeaders.add(viaHeader); MaxForwardsHeader maxForwards = this.headerFactory.createMaxForwardsHeader(70); URI uri = provider.getAddressFactory().createURI(toAddressStr); Request req = messageFactory.createRequest(uri, Request.MESSAGE, this.provider.getNewCallId(), headerFactory.createCSeqHeader(1, Request.MESSAGE), fromHeader, toHeader, viaHeaders, maxForwards); ContentTypeHeader contentType = headerFactory.createContentTypeHeader("text", "plain"); req.setContent(body,contentType); ClientTransaction ct = provider.getNewClientTransaction(req); ct.sendRequest(); } catch (Exception e) { logger.error(e); } } /** * Initialize the component */ public void setSbbContext(SbbContext context) { this.sbbContext = context; try { Context myEnv = (Context) new InitialContext().lookup("java:comp/env"); // Getting SLEE Factility timerFacility = (TimerFacility) myEnv.lookup("slee/facilities/timer"); nullACIFactory = (NullActivityContextInterfaceFactory)myEnv. lookup("slee/nullactivity/activitycontextinterfacefactory"); nullActivityFactory = (NullActivityFactory)myEnv.lookup("slee/nullactivity/factory"); // Getting JAIN SIP Resource Adaptor interfaces provider = (SleeSipProvider) myEnv.lookup("slee/resources/jainsip/1.2/provider"); addressFactory = provider.getAddressFactory(); headerFactory = provider.getHeaderFactory(); messageFactory = provider.getMessageFactory(); } catch (Exception ne) { logger.error("Failed to set sbb context",ne); } } public void unsetSbbContext() { this.sbbContext = null; } // TODO: Implement the lifecycle methods if required public void sbbCreate() throws javax.slee.CreateException {} public void sbbPostCreate() throws javax.slee.CreateException {} public void sbbActivate() {} public void sbbPassivate() {} public void sbbRemove() {} public void sbbLoad() {} public void sbbStore() {} public void sbbExceptionThrown(Exception exception, Object event, ActivityContextInterface activity) {} public void sbbRolledBack(RolledBackContext context) {} public abstract org.mobicents.slee.examples.wakeup.WakeUpSbbActivityContextInterface asSbbActivityContextInterface(ActivityContextInterface aci); /** * Attempts to find a locally registered contact address for the given URI, * using the location service interface. */ public URI findLocalTarget(URI uri, LocationSbbLocalObject locationSbbLocalObject) throws SipSendErrorResponseException { String addressOfRecord = uri.toString(); Map bindings = null; try { bindings = locationSbbLocalObject.getBindings(addressOfRecord); } catch (LocationServiceException lse) { lse.printStackTrace(); } if (bindings == null) { throw new SipSendErrorResponseException("User not found", Response.NOT_FOUND); } if (bindings.isEmpty()) { throw new SipSendErrorResponseException( "User temporarily unavailable", Response.TEMPORARILY_UNAVAILABLE); } Iterator it = bindings.values().iterator(); URI target = null; while (it.hasNext()) { RegistrationBinding binding = (RegistrationBinding) it.next(); try { target = addressFactory.createURI(binding.getContactAddress()); break; } catch (Exception e) { logger.warn("Failed to create sip uri",e); } } if (target == null) { logger.error("findLocalTarget: No contacts for " + addressOfRecord + " found."); throw new SipSendErrorResponseException( "User temporarily unavailable", Response.TEMPORARILY_UNAVAILABLE); } return target; } private SbbContext sbbContext; // This SBB's SbbContext private MessageFactory messageFactory; private SleeSipProvider provider; private TimerFacility timerFacility; private NullActivityContextInterfaceFactory nullACIFactory; private NullActivityFactory nullActivityFactory; private AddressFactory addressFactory; private HeaderFactory headerFactory; private static final Logger logger = Logger.getLogger(WakeUpSbb.class); }