/* * Copyright (C) 2005 Luca Veltri - University of Parma - Italy * * This file is part of MjSip (http://www.mjsip.org) * * MjSip is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * MjSip is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MjSip; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author(s): * Luca Veltri (luca.veltri@unipr.it) */ /* Modified by: * Daina Interrante (daina.interrante@studenti.unipr.it) */ package org.zoolu.sip.dialog; import org.zoolu.sip.address.*; import org.zoolu.sip.transaction.*; import org.zoolu.sip.dialog.*; import org.zoolu.sip.message.*; import org.zoolu.sip.header.*; import org.zoolu.sip.provider.*; import org.zoolu.tools.LogLevel; import java.util.Date; /** SubscriberDialog. */ public class SubscriberDialog extends Dialog implements TransactionClientListener { /** String "active" */ protected static final String ACTIVE="active"; /** String "pending" */ protected static final String PENDING="pending"; /** String "terminated" */ protected static final String TERMINATED="terminated"; /** The current subscribe method */ //Message subscribe=null; /** The subscribe transaction */ TransactionClient subscribe_transaction; /** The notify transaction */ //TransactionServer notify_transaction=null; /** The SubscriberDialog listener */ SubscriberDialogListener listener; /** The event package name */ String event; /** The subscription id */ String id; /** Internal state D_INIT */ protected static final int D_INIT=0; /** Internal state D_SUBSCRIBING */ protected static final int D_SUBSCRIBING=1; /** Internal state D_SUBSCRIBED */ protected static final int D_ACCEPTED=2; /** Internal state D_PENDING */ protected static final int D_PENDING=3; /** Internal state D_ACTIVE */ protected static final int D_ACTIVE=4; /** Internal state D_TERMINATED */ protected static final int D_TERMINATED=9; /** Gets the dialog state */ protected String getStatus() { switch (status) { case D_INIT : return "D_INIT"; case D_SUBSCRIBING: return "D_SUBSCRIBING"; case D_ACCEPTED : return "D_ACCEPTED"; case D_PENDING : return "D_PENDING"; case D_ACTIVE : return "D_ACTIVE"; case D_TERMINATED : return "D_TERMINATED"; default : return null; } } // *************************** Public methods ************************** /** Whether the dialog is in "early" state. */ public boolean isEarly() { return (status<D_ACCEPTED); } /** Whether the dialog is in "confirmed" state. */ public boolean isConfirmed() { return (status>=D_ACCEPTED && status<D_TERMINATED); } /** Whether the dialog is in "active" state. */ public boolean isTerminated() { return (status==D_TERMINATED); } /** Whether the subscription is "pending". */ public boolean isSubscriptionPending() { return (status>=D_ACCEPTED && status<D_ACTIVE); } /** Whether the subscription is "active". */ public boolean isSubscriptionActive() { return (status==D_ACTIVE); } /** Whether the subscription is "terminated". */ public boolean isSubscriptionTerminated() { return (status==D_TERMINATED); } /** Gets event type. */ public String getEvent() { return event; } /** Gets the event "id" parameter. */ public String getId() { return id; } // **************************** Costructors **************************** /** Creates a new SubscriberDialog. */ public SubscriberDialog(SipProvider sip_provider, /*String subscriber, String contact, */String event, String id, SubscriberDialogListener listener) { super(sip_provider); this.listener=listener; this.subscribe_transaction=null; //this.from_url=new NameAddress(subscriber); //if (contact!=null) this.contact_url=new NameAddress(contact); //else this.contact_url=from_url; this.event=event; this.id=null; changeStatus(D_INIT); } // *************************** Public methods ************************** /** Sends a new SUBSCRIBE request (starts a new subscription). * It also initializes the dialog state information. * @param target the target url (and display name) * @param subscriber the subscriber url (and display name) * @param contact the contact url OR the contact user-name */ public void subscribe(String target, String subscriber, String contact, int expires) { printLog("inside subscribe(target="+target+",subscriber="+subscriber+",contact="+contact+",id="+id+",expires="+expires+")",LogLevel.MEDIUM); SipURL request_uri=new SipURL(target); NameAddress to_url=new NameAddress(target); NameAddress from_url=new NameAddress(subscriber); NameAddress contact_url; if (contact!=null) contact_url=new NameAddress(contact); else contact_url=from_url; String content_type=null; String body=null; Message req=MessageFactory.createSubscribeRequest(sip_provider,request_uri,to_url,from_url,contact_url,event,id,content_type,body); req.setHeader(new AcceptHeader("application/pidf+xml")); req.setExpiresHeader(new ExpiresHeader(expires)); subscribe(req); } /** Sends a new SUBSCRIBE request (starts a new subscription). * It also initializes the dialog state information. * @param req the SUBSCRIBE message */ public void subscribe(Message req) { printLog("inside subscribe(req)",LogLevel.MEDIUM); if (statusIs(D_TERMINATED)) { printLog("subscription already terminated: request aborted",LogLevel.MEDIUM); return; } // else if(statusIs(D_INIT)) { changeStatus(D_SUBSCRIBING); } update(UAC,req); // start client transaction subscribe_transaction=new TransactionClient(sip_provider,req,this); subscribe_transaction.request(); } /** Sends a new SUBSCRIBE request (starts a new subscription). */ public void reSubscribe(String target, String subscriber, String contact, int expires) { subscribe(target,subscriber,contact,expires); } // ************** Inherited from TransactionClientListener ************** /** When the TransactionClient is (or goes) in "Proceeding" state and receives a new 1xx provisional response */ public void onTransProvisionalResponse(TransactionClient tc, Message resp) { printLog("onTransProvisionalResponse()",LogLevel.MEDIUM); // do nothing. } /** When the TransactionClient goes into the "Completed" state receiving a 2xx response */ public void onTransSuccessResponse(TransactionClient tc, Message resp) { printLog("onTransSuccessResponse()",LogLevel.MEDIUM); if(!statusIs(D_ACTIVE)) { changeStatus(D_ACCEPTED); update(UAC,resp); StatusLine status_line=resp.getStatusLine(); if (listener!=null) listener.onDlgSubscriptionSuccess(this,status_line.getCode(),status_line.getReason(),resp); } else if(statusIs(D_ACTIVE)) { StatusLine status_line=resp.getStatusLine(); if (listener!=null) listener.onDlgSubscriptionSuccess(this,status_line.getCode(),status_line.getReason(),resp); } } /** When the TransactionClient goes into the "Completed" state receiving a 300-699 response */ public void onTransFailureResponse(TransactionClient tc, Message resp) { printLog("onTransFailureResponse()",LogLevel.MEDIUM); changeStatus(D_TERMINATED); StatusLine status_line=resp.getStatusLine(); if (listener!=null) listener.onDlgSubscriptionFailure(this,status_line.getCode(),status_line.getReason(),resp); } /** When the TransactionClient goes into the "Terminated" state, caused by transaction timeout */ public void onTransTimeout(TransactionClient tc) { printLog("onTransTimeout()",LogLevel.MEDIUM); changeStatus(D_TERMINATED); if (listener!=null) listener.onDlgSubscribeTimeout(this); } // ***************** Inherited from SipProviderListener ***************** /** When a new Message is received by the SipProvider. */ public void onReceivedMessage(SipProvider sip_provider, Message msg) { printLog("onReceivedMessage()",LogLevel.MEDIUM); if (statusIs(D_TERMINATED)) { printLog("subscription already terminated: message discarded",LogLevel.MEDIUM); return; } // else if (msg.isRequest() && msg.isNotify()) { TransactionServer ts=new TransactionServer(sip_provider,msg,null); ts.respondWith(MessageFactory.createResponse(msg,200,SipResponses.reasonOf(200),null)); NameAddress to=msg.getToHeader().getNameAddress(); NameAddress from=msg.getFromHeader().getNameAddress(); NameAddress contact=null; if (msg.hasContactHeader()) contact=msg.getContactHeader().getNameAddress(); String state=null; if (msg.hasSubscriptionStateHeader()) state=msg.getSubscriptionStateHeader().getState(); String content_type=null; if (msg.hasContentTypeHeader()) content_type=msg.getContentTypeHeader().getContentType(); String body=null; if (msg.hasBody()) body=msg.getBody(); if (listener!=null) listener.onDlgNotify(this,to,from,contact,state,content_type,body,msg); if (state!=null) { if (state.equalsIgnoreCase(ACTIVE) && !statusIs(D_TERMINATED)) { changeStatus(D_ACTIVE); } else if (state.equalsIgnoreCase(PENDING) && statusIs(D_ACCEPTED)) { changeStatus(D_PENDING); } else if (state.equalsIgnoreCase(TERMINATED) && !statusIs(D_TERMINATED)) { changeStatus(D_TERMINATED); if (listener!=null) listener.onDlgSubscriptionTerminated(this); } } } else { printLog("message is not a NOTIFY: message discarded",LogLevel.HIGH); } } //**************************** Logs ****************************/ /** Adds a new string to the default Log */ protected void printLog(String str, int level) { if (log!=null) log.println("SubscriberDialog#"+dialog_sqn+": "+str,level+SipStack.LOG_LEVEL_DIALOG); } }