import os
import threading
import commands
import subprocess
import sys
import time

class IperfThread(threading.Thread):
    """
    Class responsible for calling a thread that instantiates a IperfTest object in a new thread.

    IperfTest objects must be passed as argument in the IperfThread Call.

    Example:

    #Creates an IperfTest object
    test = IperfTest()
    #Uses IperfThread to execute method runTest of object "test"
    IperfThread("1",test).start()
    """
    def run(self):
        """When called, given an object, executes its runTest method.
        Could be modified to run other methods as well"""
        self.object.runTest()
	time.sleep(self.object.samplePeriod)
	self.object.done = True
	self.object.writeResultFile()
	os.popen("ssh root@" + str(self.object.measureAddress) + " \" " + "killall iperf" + " \" ")	
    def __init__(self, threadId,object):
        threading.Thread.__init__(self)
        self.object = object
        self.threadId = threadId

class ServerThread(threading.Thread):
    def run(self):
        """When called, given an object, executes its runServer method.
        Could be modified to run other methods as well"""
        self.object.runServer()
    def __init__(self, threadId,object):
        threading.Thread.__init__(self)
        self.object = object
        self.threadId = threadId

class IperfTest():	
	def __init__(self,duration=10,samplePeriod=1,packetSize=1470,kbitRate=50000,destination="floresta",resultName="testando",measureAddress="floresta",portNumber="5001"):
		self.duration = duration
		self.samplePeriod = float(samplePeriod)
		self.packetSize = packetSize
		self.kbitRate = kbitRate
		self.destination = destination
		self.done = False
		self.lastMeasure = ""
		self.measureCollectedStatus = True
		self.finalResult = ""
		self.resultName = resultName
		self.measureAddress = measureAddress
		self.portNumber = portNumber
		self.sampleNumber = 1
	
	def runTest(self):
		#Run the test and store the last measure in self.lastMeasure variable
		cmd = "iperf -c " + str(self.destination) + " -i " + str(self.samplePeriod) + " -t " + str(self.duration) + " -b "  + str(self.kbitRate) + "k -f k -y C -x CMSV -l " + str(self.packetSize) + " -p " + str(self.portNumber)
		time.sleep(1)
		client = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
		#for line in iter(p.stdout.readline, ''):
		#	self.__setLastMeasure(line)
		#	self.__addMeasureResult(line)
   		#	sys.stdout.flush() 
		#p.wait()
		ServerThread("2",self).start()
		client.wait()		
		#print "Matando Server"	
		#
		#print "Server Morreu"		
		#server.terminate()			

	def runServer(self):
		#Run the Iperf Server and stores information. It should be executed by a thread
		cmd = "ssh root@" + str(self.measureAddress) + " \" " + "iperf -su -i " + str(self.samplePeriod) +" -f k -y C -x CMSV -l " + str(self.packetSize) + " -p " + str(self.portNumber) + " \" "
		server = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
		for line in iter(server.stdout.readline, "") :
			self.__setLastMeasure(line)
   			sys.stdout.flush()		


	def setMeasureCollectedStatus(self,status):
		self.measureCollectedStatus = status

	def getMeasureCollectedStatus(self):
		return self.measureCollectedStatus

	def __setLastMeasure(self,line):
		#Store the new measurment resultNamein the lastMeasure attribute and set False to measureCollectedStatus, indicating that the measure is new.
		lineSplit = line.split(",")

		#Consider as result only the client response(Server response, that is the last line, is ignored)
		if lineSplit[6] != ("0.0-" + str(self.duration) + ".0"):
			self.lastMeasure = lineSplit[8]
			self.setMeasureCollectedStatus(False)
			resultLine = str(float(self.sampleNumber)*self.samplePeriod) + " " + str(float(self.lastMeasure)/float(1000))
			self.__addMeasureResult(resultLine)
		self.sampleNumber = self.sampleNumber + 1


	def getLastMeasure(self):
		#Collect the new measurment in the lastMeasure attribute and set True to measureCollectedStatus, indicatind that the measure has been collected.If the measure is not new this method returns -1
		if self.getMeasureCollectedStatus() == True :
			return -1
		self.setMeasureCollectedStatus(True)
		return self.lastMeasure

	def __addMeasureResult(self,line):
		#Add a measure to the final result
		self.finalResult = self.finalResult + line + "\n"

	def getMeasureResult(self):
		return self.finalResult
		
	def writeResultFile(self):
		#Write the result file specified by self.resultName
		resultFile = open(self.resultName,'w')
		resultFile.write(self.getMeasureResult())
		resultFile.close()

        		

#This works for me:
#import subprocess as sp
