############################################################################
##
## Copyright (c) 2000-2001 BalaBit IT Ltd, Budapest, Hungary
## All rights reserved.
##
## $Id: Router.py,v 1.3.2.2 2001/09/04 09:42:56 bazsi Exp $
##
############################################################################

"""Module defining the Router interface for directing connections to the appropriate servers.

This module defines the 'AbstractRouter' interface and derived classes,
which are used when determining the server address to connect to.
"""

from SockAddr import SockAddrInet

class AbstractRouter:
	"""Abstract class encapsulating the Router interface.
	
	This abstract class encapsulates the Router interface, which is used
	to determine the destination address of a given service. Different
	implementations of this interface perform Transparent routing
	(directing the client to its original destination), and Directed
	routing (directing the client to a given destination).
	
	The result of this class can be overridden by the proxy using
	the 'setServerAddress' method.
	"""
	def routeConnection(self, session):
		"""Function called to perform connection routing.
		
		This function is called to determine the destination address
		of this session, and place it in session.server_address
		
		Arguments
		
		  self -- this instance
		  
		  session -- session we belong to
		"""
		raise NotImplementedError

class TransparentRouter:
	"""Class implementing transparent routing.
	
	This class implements transparent routing, which means it directs
	the proxy to connect to the original destination of the client.
	
	Attributes
	
	  forced_port -- set the destination port to this value if non-zero
	"""
	def __init__(self, forced_port=0):
		"""Constructor to initialize a TransparentRouter instance.
		
		This constructor initializes a TransparentRouter instance
		by storing arguments as attributes.
		
		Arguments
		
		  self -- this instance
		  
		  forced_port -- set the destination port to this value if non-zero
		"""
		self.forced_port = forced_port

	def routeConnection(self, session):
		"""Overridden function to perform routing.
		
		This function sets 'session.server_address' to the transparent
		destination as stored in 'session.client_dest'.
		
		Arguments
		
		  self -- this instance
		  
		  session -- session we belong to
		"""
		session.server_address = SockAddrInet(session.client_dest.ip_s, session.client_dest.port)
		if self.forced_port:
			session.server_address.port = self.forced_port

class DirectedRouter:
	"""Class implementing directed routing.
	
	This class imlements directed routing, which means it connects
	each session to a fixed address.
	
	Attributes
	
	  dest_addr -- fixed destination address to connect to
	
	"""
	def __init__(self, dest_addr):
		"""Constructor to initialize a DirectedRouter.
		
		This constructor initializes a DirectedRouter instance by
		storing arguments as attributes.
		
		Arguments
		
		  self -- this instance
		  
		  dest_addr -- fixed destination address to connect to
		"""
		self.dest_addr = dest_addr

	def routeConnection(self, session):
		"""Overridden function to perform routing.
		
		This function simply sets 'session.server_address' to
		'self.dest_addr'.
		
		Arguments
		
		  self -- this instance
		  
		  session -- session we belong to
		"""
		session.server_address = self.dest_addr
		
class InbandRouter:
	"""Class implementing Inband routing.
	
	This class implements inband routing, which basically means that the
	destination address is not known at this time, it should be
	determined by the protocol logic. It can be used for example for
	non-transparent HTTP proxies.
	"""
	def routeConnection(self, session):
		"""Overridden function to perform routing.
		
		This function does nothing, it simply let's the protocol
		logic to choose its destination server, if it doesn't an
		exception will be raised at connection time.
		
		Arguments
		
		  self -- this instance
		  
		  session -- session we belong to
		"""
		session.server_address_inband = 1

