/* * This file was derived from libdissipate, an open source SIP library. The original file * was modified on 1/23/2001. Please see * http://www.div8.net/dissipate for more information. * * Copyright (c) 2000 Billy Biggs * * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This library 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 Library General Public * License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * */ /** * class SipCallMember * * Object to reference a member of a call. Contains the remote URI, their * current Contact URI, and their current status in the call. It also contains * their current session description, and a copy of our local session * description for this call leg. * * This class also provides an API for modifying call state to this member of * the call, such as sending an invitation to join the session, or accepting a * call. */ package org.mitre.jsip; import java.awt.Toolkit; import org.mitre.jsip.event.*; public class SipCallMember extends Object { /** * Creates a new member for this call with the given URI. Initially, * this sets the Contact URI for the call member to be the same. * @param parent * @param uri */ public SipCallMember(SipCall parent, SipUri uri) { call = parent; memberuri = uri; contacturi = uri; local = null; remote = null; status = Disconnected; parent.addMember( this ); } /** * Returns the current status of the call member. * * @return Status */ public int getStatus() { return status; } /** * Returns the most recent session description provided by the member * for sending media to them. * * @return String */ public String getSessionDescription() { return sessiondesc; } /** * Returns the MIME Content Type of the session description provided by * the call member. If none was provided, this function returns NULL. * @return MimeContentType */ public MimeContentType getSessionDescriptionType() { return sessiontype; } /** * Returns the most recently sent local session description. Provided * for reference. * @return String */ public String getLocalSessionDescription() { return localsessiondesc; } /** * Returns the MIME Content Type of the most recently sent local * session description. * @return MimeContentType */ public MimeContentType getLocalSessionDescriptionType() { return localsessiontype; } /** * Returns a text description of our current status. Basically, this * is the text from the response line of the last message we received, * or a text description of what we're currently doing or waiting for. * Useful for showing the user what is going on. * @return String */ public String getLocalStatusDescription() { return statusdesc; } /** * Returns the most recent message body we received that was not a * session description. * @return String */ public String getMostRecentMessageBody() { return recentbody; } /** * Returns the MIME type of the most recent message body we received * that was not a session description. * @return MimeContentType */ public MimeContentType getMostRecentMessageBodyType() { return recentbodytype; } /** * Sends a SIP INVITE request, asking the member to join in the session * described in the given body. The body and MIME type provided will * become the new local session description for this call member. */ public void requestInvite( String body, MimeContentType bodytype ) { if ( local != null ) { // local.cancelRequest(); local = null; // disconnect( local, 0, this, 0 ); } if ( body != null ) { localsessiondesc = body; localsessiontype = bodytype; } if ( status == Connected ) { status = ReInviteRequested; statusdesc = "Requesting session update"; } else { status = InviteRequested; statusdesc = "Requesting remote end to join session"; } local = call.newRequest( this, Sip.INVITE, body, bodytype ); // *** LOOK AT *** //connect( local, statusUpdated(), this, localStatusUpdated() ); //statusUpdated(); // localStatusUpdated(); } /** * Sends a SIP BYE request to disconnect the session. */ public void requestDisconnect( String body, MimeContentType bodytype ) { if ( status == Disconnected ) return; if ( local != null ) { // local.cancelRequest(); local = null; // disconnect( local, 0, this, 0 ); } status = Disconnecting; statusdesc = "Disconnecting"; local = call.newRequest( this, Sip.BYE, body, bodytype ); // *** LOOK AT *** //connect ( local, statusUpdate(), this, localStatusUpdated() ); //statusUpdated(); localStatusUpdated(); } /** * Disconnects the session with a request to transfer to another party. */ public void requestTransfer( SipUri transferto, String body, MimeContentType bodytype ) { if ( status == Disconnected ) return; if ( local != null ) { // local.cancelRequest(); local = null; // disconnect( local, 0, this, 0 ); } status = Disconnecting; statusdesc = "Transfering"; local = call.newRequest( this, Sip.BYE, body, bodytype, transferto ); // **** LOOK AT **** //connect( local, statusUpdated(), this, localStatusUpdated() ); //statusUpdated(); localStatusUpdated(); } /** * Sends a MESSAGE request */ public void requestMessage( String messageBody ) { if ( local != null ) { // local.cancelRequest(); local = null; } statusdesc = "Sending message"; status = MessageRequested; MimeContentType bodytype = new MimeContentType( "text/plain" ); local = call.newRequest( this, Sip.MESSAGE, messageBody, bodytype ); // localStatusUpdated(); } /** * Sends a SIP OPTIONS request, asking the member what they support. * The body and MIME type provided serve no known purpose at this time. * The response to the OPTIONS request will become the new remote * session description, so this should not be called on an active call. * It is provided here for consistency. */ public void requestOptions( String body, MimeContentType bodytype ) { if ( local != null ) { // local.cancelRequest(); local = null; // disconnect( local, 0, this, 0 ); } statusdesc = "Querying options"; local = call.newRequest( this, Sip.OPTIONS, body, bodytype ); // *** LOOK AT *** //connect( local, statusUpdated(), this, localStatusUpdated() ); //statusUpdated(); localStatusUpdated(); } /** * Accepts the invitation to join the session sent by the call member. * The body and MIME type provided will become the new local session * description for this call member. */ public void acceptInvite( String body, MimeContentType bodytype ) { if ( remote == null ) return; if ( body != null ) { localsessiondesc = body; localsessiontype = bodytype; } remote.sendResponse( new SipStatus( 200 ), body, bodytype ); status = Connected; statusdesc = "Connected"; //statusUpdated(); localStatusUpdated(); } /** * Declines the invitation to join the session sent by the call member. * The body and MIME type provided are for possibly giving a reason as * to why the call was declined. */ public void declineInvite( String body, MimeContentType bodytype ) { if ( remote == null ) return; remote.sendResponse( new SipStatus( 603 ), body, bodytype ); status = Disconnected; statusdesc = "Rejecting call invitation"; //statusUpdated(); localStatusUpdated(); } /** * Returns the URI for this call member. * * @return SipUri & */ public SipUri getUri() { return memberuri; } /** * Returns the current Contact URI for this call member. * * @return SipUri & */ public SipUri getContactUri() { return contacturi; } /** * Sets the Contact URI for this call member. * * @param newcontact */ public void setContactUri(SipUri newcontact) { contacturi = newcontact; } /** * Updates the URI for this call member. * * @param newuri */ public void setUri(SipUri newuri) { memberuri = newuri; } /** * Returns the list of URIs where we were redirected. * * @return SipUriList & */ public SipUriList getRedirectList() { return redirectlist; } /** * This signal is sent whenever the status of this call member has changed. * */ //private void statusUpdated() { // SipCall.statusUpdated(); //} /** * localStatusUpdated */ void localStatusUpdated() { MimeContentType mtype; if( local == null ) { if (SipClient.DEBUG) System.out.println( "SipCallMember: Received what was likely a retransmission, badly ignoring..." ); return; } if (SipClient.DEBUG) System.out.println( "SipCallMember: localStatusUpdated: " + local.getStatus().getCode() ); mtype = local.getFinalContentType(); if( mtype.type().equals( "application/sdp" ) ) { sessiondesc = local.getFinalMessageBody(); localsessiontype = mtype; } else { recentbody = local.getFinalMessageBody(); recentbodytype = mtype; } if( status == InviteRequested || status == ReInviteRequested ) { if( local.wasCancelled() ) { status = Disconnected; statusdesc = "Request cancelled"; local = null; } else if( local.getStatus().getCode() < 200 ) { statusdesc = local.getStatus().getReasonPhrase(); } else if( local.getStatus().getCode() < 300 ) { status = Connected; statusdesc = "Connected: " + local.getStatus().getReasonPhrase(); local = null; } else if( local.getStatus().getCode() < 400 ) { status = Redirected; statusdesc = "Redirected: " + local.getStatus().getReasonPhrase(); redirectlist = local.getFinalContactList(); local = null; } else { status = Disconnected; statusdesc = "Call Failed: " + local.getStatus().getReasonPhrase(); local = null; } } else if( status == Disconnecting ) { if( local.getStatus().getCode() >= 200 ) { status = Disconnected; statusdesc = "Response: " + local.getStatus().getReasonPhrase(); local = null; } } else { if( local.getStatus().getCode() >= 200 ) { statusdesc = "Response: " + local.getStatus().getReasonPhrase(); local = null; } } //statusUpdated(); } /** * remoteStatusUpdated */ void remoteStatusUpdated() { if( status == RequestingInvite ) { if( remote.wasCancelled() ) { status = Disconnected; statusdesc = "Request cancelled"; //statusUpdated(); } } } /** * incomingTransaction * @param newtrans */ void incomingTransaction(SipTransaction newtrans) { MimeContentType mtype; remote = newtrans; if( remote.getRequest().getMethod() == Sip.INVITE ) { // *** LOOK AT *** //connect( remote, statusUpdated(), this, remoteStatusUpdated() ); if( status == Disconnected ) { status = RequestingInvite; statusdesc = "Invitation received"; remote.sendResponse( new SipStatus( 180 ) ); } else { status = RequestingReInvite; statusdesc = "Session update requested"; } mtype = remote.getRequestMessageContentType(); if( ( mtype != null ) && ( mtype.type().equals( "application/sdp" ) ) ) { sessiontype = mtype; sessiondesc = remote.getRequestMessageBody(); } else { recentbodytype = mtype; recentbody = remote.getRequestMessageBody(); } // send a CallEvent here to notify the user of the request if (SipClient.DEBUG) System.out.println("Sending CallEvent request "); CallListener callListener = SipClient.getSipClient().getCallListener(); if ( callListener != null ) { // Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent( new CallEvent( SipClient.getSipClient(), remote.getRequest(), CallEvent.CALLREQUEST_ID ) ); CallEvent ce = new CallEvent( SipClient.getSipClient(), remote.getRequest(), CallEvent.CALLREQUEST_ID ); callListener.requestReceived( ce ); } } else if( remote.getRequest().getMethod() == Sip.BYE ) { status = Disconnected; statusdesc = "Remote end disconnected"; } // statusUpdated(); remoteStatusUpdated(); // I think } SipUri memberuri; SipUri contacturi; int status; SipCall call; SipTransaction local; SipTransaction remote; SipUriList redirectlist; String sessiondesc; MimeContentType sessiontype; String localsessiondesc; MimeContentType localsessiontype; String statusdesc; String recentbody; MimeContentType recentbodytype; // class variables static final int Disconnected = 0; static final int InviteRequested = 1; static final int ReInviteRequested = 2; static final int RequestingInvite = 3; static final int RequestingReInvite = 4; static final int Redirected = 5; static final int Connected = 6; static final int Disconnecting = 7; static final int MessageRequested = 8; }