/*
 * 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)
 */

package org.zoolu.sip.provider;


import org.zoolu.sip.message.Message;


/** SipInterface is actually the SIP SAP (Service Access Point) and can be used to send
  * and receive SIP messages associated with a specific method, transaction, or dialog.
  * <p/>
  * SipInterface provides a simple interface to the multiplexing function provided
  * by the SipProvider layer.
  * <br/> It simply wraps the SipProvider by adding and removing the listener
  * for capturing received SIP messages.
  * <p/>
  * When creating a new SipInterface the following parameters, have to be specified:
  * <b> - <i>sip_provider<i/> is the SipProvider the SipInterface has to be bound to,
  * <b> - <i>id<i/> is the SIP interface identifier the SipInterface has to be bound to,
  * <b> - <i>listener<i/> is the SipInterfaceListener that received messages are passed to.
  * <p/>
  * The SIP interface <i>id<i/> specifies the type of messages the listener is going to
  * receive for. Together with the <i>sip_provider<i/>, it represents the complete SIP
  * Service Access Point (SAP) address/identifier used for demultiplexing SIP messages
  * at receiving side. 
  * <p/>
  * The identifier can be of one of the three following types: transaction_id, dialog_id,
  * or method_id. These types of identifiers characterize respectively:
  * <br> - messages within a specific transaction,
  * <br> - messages within a specific dialog,
  * <br> - messages related to a specific SIP method.
  * It is also possible to use the the identifier ANY to specify 
  * <br> - all messages that are out of any transactions, dialogs, or already specified
  *        method types.
  * <p>
  * When receiving a message, the underling SipProvider first tries to look for
  * a SipInterface associated to the corresponding transaction, then looks for
  * a SipInterface associated to the corresponding dialog, then for
  * a SipInterface associated to the corresponding method type, and finally for
  * a SipInterface associated to ANY messages.
  * If the present SipInterface id matches, the SipInterfaceListener method
  * <i>onReceivedMessage()</i> is fired.
  */
public class SipInterface implements SipProviderListener
{

   /** SipProvider */
   SipProvider sip_provider;  

   /** Identifier */
   Identifier id;  

   /** SipInterfaceListener */
   SipInterfaceListener listener;  
   

   // *************************** Costructors ***************************

   /** Creates a new SipInterface. */ 
   public SipInterface(SipProvider sip_provider, SipInterfaceListener listener)
   {  this.sip_provider=sip_provider;
      this.listener=listener;
      id=SipProvider.ANY;
      sip_provider.addSipProviderListener(id,this);
   }


   /** Creates a new SipInterface. */ 
   public SipInterface(SipProvider sip_provider, Identifier id, SipInterfaceListener listener)
   {  this.sip_provider=sip_provider;
      this.listener=listener;
      this.id=id;
      sip_provider.addSipProviderListener(id,this);
   }


   // ************************** Public methods *************************

   /** Close the SipInterface. */ 
   public void close()
   {  sip_provider.removeSipProviderListener(id);
   }


   /** Gets the SipProvider. */ 
   public SipProvider getSipProvider()
   {  return sip_provider;
   }


   /** Sends a Message, specifing the transport portocol, nexthop address and port.
     * <p> This is a low level method and
     * forces the message to be routed to a specific nexthop address, port and transport,
     * regardless whatever the Via, Route, or request-uri, address to. 
     * <p>
     * In case of connection-oriented transport, the connection is selected as follows:
     * <br> - if an existing connection is found matching the destination
     *        end point (socket), such connection is used, otherwise
     * <br> - a new connection is established
     *
     * @return It returns a Connection in case of connection-oriented delivery
     * (e.g. TCP) or null in case of connection-less delivery (e.g. UDP)
     */
   public ConnectionIdentifier sendMessage(Message msg, String proto, String dest_addr, int dest_port, int ttl)
   {  return sip_provider.sendMessage(msg,proto,dest_addr,dest_port,ttl); 
   }

   /** Sends the message <i>msg</i>.
     * <p>
     * The destination for the request is computed as follows:
     * <br> - if <i>outbound_addr</i> is set, <i>outbound_addr</i> and 
     *        <i>outbound_port</i> are used, otherwise
     * <br> - if message has Route header with lr option parameter (i.e. RFC3261 compliant),
     *        the first Route address is used, otherwise
     * <br> - the request's Request-URI is considered.
     * <p>
     * The destination for the response is computed based on the sent-by parameter in
     *     the Via header field (RFC3261 compliant)
     * <p>
     * As transport it is used the protocol specified in the 'via' header field 
     * <p>
     * In case of connection-oriented transport:
     * <br> - if an already established connection is found matching the destination
     *        end point (socket), such connection is used, otherwise
     * <br> - a new connection is established
     *
     * @return Returns a ConnectionIdentifier in case of connection-oriented delivery
     * (e.g. TCP) or null in case of connection-less delivery (e.g. UDP)
     */
   public ConnectionIdentifier sendMessage(Message msg)
   {  return sip_provider.sendMessage(msg); 
   }


   /** Sends the message <i>msg</i> using the specified connection. */
   public ConnectionIdentifier sendMessage(Message msg, ConnectionIdentifier conn_id)
   {  return sip_provider.sendMessage(msg,conn_id);
   }


   //************************* Callback methods *************************
   
   /** When a new Message is received by the SipProvider. */
   public void onReceivedMessage(SipProvider sip_provider, Message message)
   {  if (listener!=null) listener.onReceivedMessage(this,message);
   }

}
