###############################################################################
#                                                                             #
#   Copyright 2005 University of Cambridge Computer Laboratory.               #
#                                                                             #
#   This file is part of Nprobe.                                              #
#                                                                             #
#   Nprobe 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.                                       #
#                                                                             #
#   Nprobe 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 Nprobe; if not, write to the Free Software                     #
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA #
#                                                                             #
###############################################################################


###############################################################################
###############################################################################
#
# Model implementation dependant parameters of TCP stacks
#
##############################################################################
##############################################################################

import string
import copy

##############################################################################
##############################################################################

MAX_IWF = 6

##############################################################################
##############################################################################

#
# Bundle up TCP Implementations
#

class TCP_Imps:

    def __init__(self):

	#self.imps_list = []
	self.imps_dict = {}

	#
	# Pre-defined implementations go here
	#

	self.store(TCP_Imp('Auto', keep=1, IW_fact=0, ssthresh=0))
	self.store(TCP_Imp('Gen', keep=1, IW_fact=1))

	#
	# Marker for given up
	#
	self.give_up = TCP_Imp('Give up', keep=0, IW_fact=-1, ssthresh=-1)

	
	#
	# Set default imps here
	#
	self.simp_default = self.imps_dict['Gen']
	self.cimp_default = self.imps_dict['Gen']
        
	self.simp_start = self.imps_dict['Auto']
	self.cimp_start = self.imps_dict['Auto']

	self.simp_curr = self.simp_start
	self.cimp_curr = self.cimp_start

	#print 'TCP Implementations initialised'

##############################################################################

    def set_start(self):

	self.simp_curr = self.simp_start
	self.cimp_curr = self.cimp_start

##############################################################################

    def imp_stored(self, imp):

	return self.imps_dict.has_key(imp.make_sig())

##############################################################################

    def store(self, imp):
	
	#self.imps_list.append(imp)
	self.imps_dict[imp.make_sig()] = imp
	imp.kept = 1

	#print 'TCP Implementation %s stored ' % (imp.sig)

##############################################################################

    def have_equiv(self, imp):

## 	for i in self.imps_list:
## 	    if i.cmp(imp):
## 		return i

	sig = imp.make_sig()
	if self.imps_dict.has_key(sig):
	    return self.imps_dict[sig]

	return imp

##############################################################################

##     def curr_imps(self):

## 	return self.simp_curr, self.cimp_curr
	


##############################################################################
##############################################################################

#
# TCP Implementation class
#


class TCP_Imp: 

    def __init__(self, name, keep=0, IW_fact=2, ssthresh=65535, mss=None, nmss=None):

	self.base = self # for cloned/modified imps
	self.name = name # this is the base name
	self.sig = name  # this is any modifiers to the base
	self.kept = keep

	self.iw_fact = IW_fact
	self.ssthresh = ssthresh
	self.mss = mss   # mss used if different from negotiated
	self.nmss = nmss # negotiated

	return


##############################################################################
 
    def clone(self, mods):

## 	i = TCP_Imp(name)

## 	i.iw_fact = self.iw_fact
## 	i.ssthresh = self.ssthresh
## 	i.mss = self.mss

	i = copy.copy(self) 
	i.sig = None
	i.kept = 0
	for mod in mods:
	    setattr(i, mod[0], mod[1])

	return i

##############################################################################

##     def new_name(self, par, val):
	    


##############################################################################

## 	name = self.name
## 	valstr = '%d' % (val)
## 	pos = string.find(name, par)
## 	if pos >= 0:
## 	    #print 'name %s pos = %d' % (name, pos)
## 	    pos = pos + len(par)
## 	    valend  = pos
## 	    try:
## 		while '0' <= name[valend] <= '9':
## 		    valend = valend + 1
## 	    except IndexError:
## 		pass
## 	    #print 'newpos %d' % (pos)
## 	    oldval = string.atoi(name[pos:valend])
## 	    if oldval == val:
## 		return name
## 	    newname = name[:pos] + valstr + name[valend:]
## 	else:
## 	    newname = name + par + valstr

## 	return newname
	    


##############################################################################
	

    def make_sig(self):
	
	if self.sig:
	    return self.sig
	elif self.base == self:
	    self.sig = self.name
	    return self.sig
	b = self.base
	s = b.name
	if self.iw_fact != b.iw_fact:
	    s += '_IW%d' % (self.iw_fact)
	if self.ssthresh != b.ssthresh:
	    s += '_SST%d' % (self.iw_thresh)
	if self.mss != b.mss or self.nmss != b.nmss:
	    s += '_MSS%d/%d' % (self.mss, self.nmss)

	self.sig = s
	return s


##############################################################################
 
    def descr(self):

        return (self.name, self.iw_fact, self.ssthresh, self.mss, self.nmss)


##############################################################################
 
    def descr_str(self):

        #return 'Imp=%s IWF=%d SST=%d MSS=%d NMSS=%d' % (self.name, self.iw_fact, self.ssthresh, self.mss, self.nmss)
        #print self.name, self.iw_fact, self.ssthresh, self.mss
        s = 'Imp=%s IWF=%d SST=%d ' % (self.name, self.iw_fact, self.ssthresh)
        if self.mss:
            s += 'MSS=%d ' % (self.mss)
        if self.nmss:
            s += 'NMSS=%d ' % (self.nmss)

        return s
    
##############################################################################
 
    def print_self(self):
	
	print 'TCP Implementation %s' % (self.name)
	print '\tIW fact = %d' % (self.iw_fact)
	print '\t Ssthresh = %d' % (self.ssthresh)


##############################################################################
 
    #
    # Compare implementations - return 1 if same
    #
    def cmp(self, b):

## 	if self.iw_fact != b.iw_fact \
## 	   or self.ssthresh != b.ssthresh \
## 	   or self.mss != b.mss:
## 	    ret = 0
## 	else:
## 	    ret= 1

	if self.make_sig() == b.make_sig():
	    ret = 1
	else:
	    ret = 0
	    
	if ret:
	    s = 'SAME'
	else:
	    s = 'DIFFERENT'
	#print 'comparing %s %s - %s' % (self.name, b.name, s)

	return ret


##############################################################################
 
    #
    # Compare implementation i to list of imps - return i and add to list 
    # if not equivalent otherwise return equivalent
    #
    def already_have(self, ilist):

	for i in ilist:
	    if self.cmp(i):
		return i

	ilist.append(self)
	return self


##############################################################################
##############################################################################
