Package local.server

Source Code of local.server.Proxy

/*
* Copyright (C) 2005 Luca Veltri - University of Parma - Italy
*
* This source code 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.
*
* This source code 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 this source code; 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 local.server;


import org.zoolu.sip.address.*;
import org.zoolu.sip.provider.*;
import org.zoolu.sip.header.RequestLine;
import org.zoolu.sip.header.Header;
import org.zoolu.sip.header.ViaHeader;
import org.zoolu.sip.header.MaxForwardsHeader;
import org.zoolu.sip.header.MultipleHeader;
import org.zoolu.sip.header.RouteHeader;
import org.zoolu.sip.header.RecordRouteHeader;
import org.zoolu.sip.message.Message;
import org.zoolu.sip.message.MessageFactory;
import org.zoolu.sip.message.SipResponses;
import org.zoolu.tools.LogLevel;


//import java.util.Enumeration;
import java.util.Vector;
import java.io.BufferedReader;
import java.io.InputStreamReader;


/** Class Proxy implement a Proxy SIP Server.
  * It extends class Registrar. A Proxy can work as simply SIP Proxy,
  * or it can handle calls for registered users.
  */
public class Proxy extends Registrar
{  
   /** Log of processed calls */
   CallLogger call_logger;

   /** Costructs a void Proxy */
   protected Proxy() {}

   /** Costructs a new Proxy that acts also as location server for registered users. */
   public Proxy(SipProvider provider, ServerProfile server_profile)
   {  super(provider,server_profile);
      if (server_profile.call_log) call_logger=new CallLoggerImpl(SipStack.log_path+"//"+provider.getViaAddress()+"."+provider.getPort()+"_calls.log");
   }


   /** When a new request is received for the local server. */
   public void processRequestToLocalServer(Message msg)
   {  printLog("inside processRequestToLocalServer(msg)",LogLevel.MEDIUM);
      if (msg.isRegister())
      {  super.processRequestToLocalServer(msg);
      }
      else
      if (!msg.isAck())
      {  // send a stateless error response
         //int result=501; // response code 501 ("Not Implemented")
         //int result=485; // response code 485 ("Ambiguous");
         int result=484; // response code 484 ("Address Incomplete");
         Message resp=MessageFactory.createResponse(msg,result,SipResponses.reasonOf(result),null);
         sip_provider.sendMessage(resp);
      }
   }


   /** When a new request message is received for a local user */
   public void processRequestToLocalUser(Message msg)
   {  printLog("inside processRequestToLocalUser(msg)",LogLevel.MEDIUM);

      if (server_profile.call_log) call_logger.update(msg);

      if (server_profile.do_proxy_authentication && !msg.isAck() && !msg.isCancel())
      {  // check message authentication
         Message err_resp=as.authenticateProxyRequest(msg)
         if (err_resp!=null)
         {  sip_provider.sendMessage(err_resp);
            return;
         }
      }

      // message targets
      Vector targets=getTargets(msg);
     
      if (targets.isEmpty())
      {  // try to treat the request-URI as a local username or phone URL with a prefix-based nexthop rule
         SipURL request_uri=msg.getRequestLine().getAddress();
         SipURL new_target=getPhoneTarget(request_uri);
         if (new_target!=null) targets.addElement(new_target.toString());
      }
      if (targets.isEmpty())
      {  printLog("No target found, message discarded",LogLevel.HIGH);
         if (!msg.isAck()) sip_provider.sendMessage(MessageFactory.createResponse(msg,404,SipResponses.reasonOf(404),null));
         return;
      }          
     
      printLog("message will be forwarded to all user's contacts",LogLevel.MEDIUM);
      for (int i=0; i<targets.size(); i++)
      {  SipURL url=new SipURL((String)(targets.elementAt(i)));
         Message request=new Message(msg);
         request.removeRequestLine();
         request.setRequestLine(new RequestLine(msg.getRequestLine().getMethod(),url));
        
         updateProxingRequest(request);
         sip_provider.sendMessage(request);
      }
   }

  
   /** When a new request message is received for a remote UA */
   public void processRequestToRemoteUA(Message msg)
   {  printLog("inside processRequestToRemoteUA(msg)",LogLevel.MEDIUM);
  
      if (call_logger!=null) call_logger.update(msg);

      if (!server_profile.is_open_proxy)
      {  // check whether the caller is a local user
         SipURL from_url=msg.getFromHeader().getNameAddress().getAddress();
         String from_username=from_url.getUserName();
         String from_hostaddr=from_url.getHost();
         String caller=(from_username==null)? from_hostaddr : from_username+"@"+from_hostaddr;
         if (!location_service.hasUser(caller))
         {  // but do not filter messages directed to local users
            SipURL to_url=msg.getToHeader().getNameAddress().getAddress();
            String to_username=to_url.getUserName();
            String to_hostaddr=to_url.getHost();
            String callee=(to_username==null)? to_hostaddr : to_username+"@"+to_hostaddr;
            if (!location_service.hasUser(callee))
            {  // both caller and callee are not registered with the local server
               printLog("both users "+caller+" and "+callee+" are not registered with the local server: proxy denied.",LogLevel.HIGH);
               sip_provider.sendMessage(MessageFactory.createResponse(msg,503,SipResponses.reasonOf(503),null));
               return;
            }
         }
      }
     
      if (server_profile.do_proxy_authentication && !msg.isAck() && !msg.isCancel())
      {  // check message authentication
         Message err_resp=as.authenticateProxyRequest(msg)
         if (err_resp!=null)
         {  sip_provider.sendMessage(err_resp);
            return;
         }
      }

      updateProxingRequest(msg);     
      sip_provider.sendMessage(msg);
   }

  
   /** Processes the Proxy headers of the request.
     * Such headers are: Via, Record-Route, Route, Max-Forwards, etc. */
   protected Message updateProxingRequest(Message msg)
   {  printLog("inside updateProxingRequest(msg)",LogLevel.LOW);

      // remove Route if present
      boolean is_on_route=false
      if (msg.hasRouteHeader())
      {  MultipleHeader mr=msg.getRoutes();
         SipURL route=(new RouteHeader(mr.getTop())).getNameAddress().getAddress();
         if (isResponsibleFor(route.getHost(),route.getPort()))
         {  mr.removeTop();
            if (mr.size()>0) msg.setRoutes(mr);
            else msg.removeRoutes();
            is_on_route=true;
         }
      }
      // add Record-Route?
      if (server_profile.on_route && msg.isInvite() && !is_on_route)
      {  SipURL rr_url;
         if (sip_provider.getPort()==SipStack.default_port) rr_url=new SipURL(sip_provider.getViaAddress());
         else rr_url=new SipURL(sip_provider.getViaAddress(),sip_provider.getPort());
         if (server_profile.loose_route) rr_url.addLr();
         RecordRouteHeader rrh=new RecordRouteHeader(new NameAddress(rr_url));
         msg.addRecordRouteHeader(rrh);
      }
      // which protocol?
      String proto=null;
      if (msg.hasRouteHeader())
      {  SipURL route=msg.getRouteHeader().getNameAddress().getAddress();
         if (route.hasTransport()) proto=route.getTransport();
      }
      else proto=msg.getRequestLine().getAddress().getTransport();
      if (proto==null) proto=sip_provider.getDefaultTransport();
     
      // add Via
      ViaHeader via=new ViaHeader(proto,sip_provider.getViaAddress(),sip_provider.getPort());
      if (sip_provider.isRportSet()) via.setRport();
      String branch=sip_provider.pickBranch(msg);
      if (server_profile.loop_detection)
      {  String loop_tag=msg.getHeader(Loop_Tag).getValue();
         if (loop_tag!=null)
         {  msg.removeHeader(Loop_Tag);
            branch+=loop_tag;
         }
      }
      via.setBranch(branch);
      msg.addViaHeader(via);

      // decrement Max-Forwards
      MaxForwardsHeader maxfwd=msg.getMaxForwardsHeader();
      if (maxfwd!=null) maxfwd.decrement();
      else maxfwd=new MaxForwardsHeader(SipStack.max_forwards);
      msg.setMaxForwardsHeader(maxfwd);

      // domain name routing
      if (server_profile.domain_routing_rules!=null && server_profile.domain_routing_rules.length>0)
      {  RequestLine rl=msg.getRequestLine();
         SipURL request_uri=rl.getAddress();
         for (int i=0; i<server_profile.domain_routing_rules.length; i++)
         {  RoutingRule rule=(RoutingRule)server_profile.domain_routing_rules[i];
            SipURL nexthop=rule.getNexthop(request_uri);
            if (nexthop!=null)
            {  printLog("domain-based routing: "+rule.toString()+": YES",LogLevel.MEDIUM);
               printLog("target="+nexthop.toString(),LogLevel.MEDIUM);
               rl=new RequestLine(rl.getMethod(),nexthop);
               msg.setRequestLine(rl);
               break;
            }
            else printLog("prefix-based routing: "+rule.toString()+": NO",LogLevel.MEDIUM);
         }
      }
     

      // check whether the next Route is formed according to RFC2543
      msg.rfc2543RouteAdapt();
             
      return msg;                            
   }
  

   /** When a new response message is received */
   public void processResponse(Message resp)
   {  printLog("inside processResponse(msg)",LogLevel.MEDIUM);
  
      if(call_logger!=null) call_logger.update(resp);

      updateProxingResponse(resp);
     
      if (resp.hasViaHeader()) sip_provider.sendMessage(resp);
      else
         printLog("no VIA header found: message discarded",LogLevel.HIGH);           
   }
  
  
   /** Processes the Proxy headers of the response.
     * Such headers are: Via, .. */
   protected Message updateProxingResponse(Message resp)
   {  printLog("inside updateProxingResponse(resp)",LogLevel.MEDIUM);
      ViaHeader vh=new ViaHeader((Header)resp.getVias().getHeaders().elementAt(0));
      if (vh.getHost().equals(sip_provider.getViaAddress())) resp.removeViaHeader();
      return resp;
   }
  

   /** Tries to find the target for a username or phone URL not registered within the location service. */
   protected SipURL getPhoneTarget(SipURL request_uri)
   {  String username=request_uri.getUserName();
      if (username!=null && isPhoneNumber(username))
      {  printLog(username+" is a phone number",LogLevel.MEDIUM);
         for (int i=0; i<server_profile.phone_routing_rules.length; i++)
         {  RoutingRule rule=(RoutingRule)server_profile.phone_routing_rules[i];
            SipURL nexthop=rule.getNexthop(request_uri);
            if (nexthop!=null)
            {  printLog("prefix-based routing: "+rule.toString()+": YES",LogLevel.MEDIUM);
               printLog("target="+nexthop.toString(),LogLevel.MEDIUM);
               return nexthop;
            }
            else printLog("prefix-based routing: "+rule.toString()+": NO",LogLevel.MEDIUM);
         }
      }
      return null;
   }


   /** Whether the String is a phone number. */
   protected boolean isPhoneNumber(String str)
   {  if (str==null || str.length()==0) return false;
      for (int i=0; i<str.length(); i++)
      {  char c=str.charAt(i);
         if (c!='+' && c!='-' && (c<'0' || c>'9')) return false;
      }
      return true;
   }  


   // ****************************** Logs *****************************

   /** Adds a new string to the default Log */
   private void printLog(String str, int level)
   {  if (log!=null) log.println("Proxy: "+str,level+SipStack.LOG_LEVEL_UA)
   }


   // ****************************** MAIN *****************************

   /** The main method. */
   public static void main(String[] args)
   { 
        
      String file=null;
      boolean prompt_exit=false;
     
      for (int i=0; i<args.length; i++)
      {  if (args[i].equals("-f") && args.length>(i+1))
         {  file=args[++i];
            continue;
         }
         if (args[i].equals("--prompt"))
         {  prompt_exit=true;
            continue;
         }
         if (args[i].equals("-h"))
         {  System.out.println("usage:\n   java Proxy [options] \n");
            System.out.println("   options:");
            System.out.println("   -h               this help");
            System.out.println("   -f <config_file> specifies a configuration file");
            System.out.println("   --prompt         prompt for exit");
            System.exit(0);
         }
      }
                 
      SipStack.init(file);
      SipProvider sip_provider=new SipProvider(file);
      ServerProfile server_profile=new ServerProfile(file);

      new Proxy(sip_provider,server_profile);
     
      // promt before exit
      if (prompt_exit)
      try
      System.out.println("press 'enter' to exit");
         BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
         in.readLine();
         System.exit(0);
      }
      catch (Exception e) {}
   }
 
}
TOP

Related Classes of local.server.Proxy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.