/** Terminates the subscription (subscription goes into 'terminated' state). */ public void terminate(String reason) { Message req = MessageFactory.createNotifyRequest(this, event, id, null, null); SubscriptionStateHeader sh = new SubscriptionStateHeader(TERMINATED); if (reason != null) sh.setReason(reason); // sh.setExpires(0); req.setSubscriptionStateHeader(sh); notify(req); }
/** Sends a NOTIFY. */ public void notify(String state, int expires, String content_type, String body) { Message req = MessageFactory.createNotifyRequest(this, event, id, content_type, body); if (state != null) { SubscriptionStateHeader sh = new SubscriptionStateHeader(state); if (expires >= 0) sh.setExpires(expires); req.setSubscriptionStateHeader(sh); } notify(req); }
/** * Implements {@link MethodProcessor#processRequest(RequestEvent)}. Handles only NOTIFY requests * because they are the only requests concerning event package subscribers and if the processing * of a given request requires event package-specific handling, delivers the request to the * matching Subscription instance. Examples of such event package-specific handling include * handling the termination of an existing Subscription and processing the bodies of the NOTIFY * requests for active Subscriptions. * * @param requestEvent a <tt>RequestEvent</tt> specifying the SIP <tt>Request</tt> to be processed * @return <tt>true</tt> if the SIP <tt>Request</tt> specified by <tt>requestEvent</tt> was * processed; otherwise, <tt>false</tt> */ @Override public boolean processRequest(RequestEvent requestEvent) { Request request = requestEvent.getRequest(); EventHeader eventHeader = (EventHeader) request.getHeader(EventHeader.NAME); if ((eventHeader == null) || !eventPackage.equalsIgnoreCase(eventHeader.getEventType())) { /* * We are not concerned by this request, perhaps another listener * is. So don't send a 489 / Bad event answer here. */ return false; } if (!Request.NOTIFY.equals(request.getMethod())) return false; if (logger.isDebugEnabled()) logger.debug("notify received"); SubscriptionStateHeader sstateHeader = (SubscriptionStateHeader) request.getHeader(SubscriptionStateHeader.NAME); // notify must contain one (rfc3265) if (sstateHeader == null) { logger.error("no subscription state in this request"); return false; } String sstate = sstateHeader.getState(); ServerTransaction serverTransaction = getOrCreateServerTransaction(requestEvent); // first handle the case of a contact still pending // it's possible if the NOTIFY arrives before the OK CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); String callId = callIdHeader.getCallId(); Subscription subscription = getSubscription(callId); // see if the notify correspond to an existing subscription if ((subscription == null) && !SubscriptionStateHeader.TERMINATED.equalsIgnoreCase(sstate)) { if (logger.isDebugEnabled()) logger.debug("subscription not found for callId " + callId); // send a 481 response (rfc3625) Response response; try { response = protocolProvider .getMessageFactory() .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST, request); } catch (ParseException e) { logger.error("failed to create the 481 response", e); return false; } try { serverTransaction.sendResponse(response); } catch (SipException e) { logger.error("failed to send the response", e); } catch (InvalidArgumentException e) { // should not happen logger.error("invalid argument provided while trying to send the response", e); } return true; } // if we don't understand the content ContentTypeHeader ctheader = (ContentTypeHeader) request.getHeader(ContentTypeHeader.NAME); if ((ctheader != null) && !ctheader.getContentSubType().equalsIgnoreCase(contentSubType)) { // send a 415 response (rfc3261) Response response; try { response = protocolProvider .getMessageFactory() .createResponse(Response.UNSUPPORTED_MEDIA_TYPE, request); } catch (ParseException e) { logger.error("failed to create the OK response", e); return false; } // we want PIDF AcceptHeader acceptHeader; try { acceptHeader = protocolProvider.getHeaderFactory().createAcceptHeader("application", contentSubType); } catch (ParseException e) { // should not happen logger.error("failed to create the accept header", e); return false; } response.setHeader(acceptHeader); try { serverTransaction.sendResponse(response); } catch (SipException e) { logger.error("failed to send the response", e); } catch (InvalidArgumentException e) { // should not happen logger.error("invalid argument provided while trying" + " to send the response", e); } } // if the presentity doesn't want of us anymore if (SubscriptionStateHeader.TERMINATED.equalsIgnoreCase(sstate)) { // if we requested this end of subscription, subscription == null if (subscription != null) { removeSubscription(callId, subscription); subscription.processTerminatedRequest(requestEvent, sstateHeader.getReasonCode()); } } // send an OK response Response response; try { response = protocolProvider.getMessageFactory().createResponse(Response.OK, request); } catch (ParseException e) { logger.error("failed to create the OK response", e); return false; } try { serverTransaction.sendResponse(response); } catch (SipException e) { logger.error("failed to send the response", e); } catch (InvalidArgumentException e) { // should not happen logger.error("invalid argument provided while trying to send the response", e); } // transform the presence document in new presence status if (subscription != null) subscription.processActiveRequest(requestEvent, request.getRawContent()); return true; }