#!/usr/bin/python -u

#Author: Rodrigo de Souza Couto
#E-mail:souza@gta.ufrj.br
#Instituion: Grupo de Teleinformatica e Automacao - PEE/COPPE - DEL/POLI - UFRJ
#Description:This daemon receives by command line the TCP port to use, the sample rate in which the NIC information is sampled and the rate that the throughput ins informed through the socket

import socket
import os
import sys
import time
import pickle
import copy

if (len(sys.argv) < 2) or (len(sys.argv) > 4):
	print "use:%s <port> [<sampleRate>] [<showRate>]" % (sys.argv[0])
	sys.exit(1)

#Default Values

defaultSampleRate = float(0.1)
defaultShowRate = float(1)

#Settings
HOST = ''                 
PORT = int(sys.argv[1])
#Set the field used of the line gathered by /proc/net/dev
fieldUsed = int(0)
#Configure the sample period used to acces /proc/net/dev
try:
	sampleRate = float(sys.argv[2])
except:
	#Set the default value if no parameter is given
	sampleRate = defaultSampleRate
#Configure the period that the rate is sent. It is useful to sample the netowrk interface in a rate higher than the displayed 
try:
	showRate = float(sys.argv[3])
except:
	showRate = defaultShowRate

#Start server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)

while 1:
	#Wait for new connection
	conn, addr = s.accept()
	connStatus = True

	#Each entry, representing a NIC, contains another dictionary having th nic information
	nicThroughputDictionary ={}
	exception = False
	
	initialInstant = float(time.time())
	tempo = float(time.time())
	programStart = True
	data = os.popen("cat /proc/net/dev")
	
	exception = False
	
	for line in data:
		try:
			#Split the line base on ":"
			lineSplitted = line.split(":")
			nicName = lineSplitted[0]
			nicName = lineSplitted[0].replace(' ', '')
			#Check if the line is valid
			try:
				#Treat only the rx bytes (In virtual interface the rx bytes are the bytes that the virtual machine sends to its frontend in dom0)
				nicStats = lineSplitted[1]
			except:
				exception = True
			
			#Gather information if the line is valid
			if (exception == False):
				nicThroughputDictionary[str(nicName)] = {}
				nicThroughputDictionary[str(nicName)]['rxbytes'] = 0
				nicThroughputDictionary[str(nicName)]['rxbytesLast'] = 0
				nicThroughputDictionary[str(nicName)]['throughput'] = 0
				nicThroughputDictionary[str(nicName)]['updated'] = True	
				nicThroughputDictionary[str(nicName)]['rxbytes'] = nicStats.split()[fieldUsed]
			exception = False		
		except:
			pass

	exception = False
	
	while connStatus == True:
	    sampleCount = 1
	    sampleLimit = int(showRate/sampleRate)
	    sampleStart = True
	    while (sampleCount <= sampleLimit):
			if not programStart:
				initialInstant = float(time.time())
			else:
				programStart = False
			time.sleep(sampleRate)	
			data = os.popen("cat /proc/net/dev")
			finalInstant = 	float(time.time())
			for line in data:
				#Split the line base on ":"
				lineSplitted = line.split(":")
				nicName = lineSplitted[0].replace(' ', '')
				#Check if the line is valid
				try:
					#Treats only the rx bytes (In virtual interface rx bytes are the bytes that the virtual machine sends to its frontend in dom0)			
					nicStats= lineSplitted[1]
				except:
					exception = True				
				#Gather information if the line is valid
				if (exception == False):
					#Stores the name of the first interface
					#If the interface is new, then we will initialize a new entry with the except
					try:
						nicThroughputDictionary[str(nicName)]['rxbytesLast'] = nicThroughputDictionary[str(nicName)]['rxbytes']
						nicThroughputDictionary[str(nicName)]['updated'] = True
					except:
						nicThroughputDictionary[str(nicName)] = {}
						nicThroughputDictionary[str(nicName)]['rxbytes'] = 0
						nicThroughputDictionary[str(nicName)]['rxbytesLast'] = ''
						nicThroughputDictionary[str(nicName)]['throughput'] = 0
						nicThroughputDictionary[str(nicName)]['updated'] = True				
					if (sampleStart):
						nicThroughputDictionary[str(nicName)]['throughput'] = 0				
					nicThroughputDictionary[str(nicName)]['rxbytes'] = int(nicStats.split()[fieldUsed])
					#Evaluates the throughput in this sample
					#Check if the entry is new
					if (nicThroughputDictionary[str(nicName)]['rxbytesLast'] != ''):
						byteDifference = int(nicThroughputDictionary[str(nicName)]['rxbytes']) - int(nicThroughputDictionary[str(nicName)]['rxbytesLast'])
						throughputSample = (float(byteDifference)/float(finalInstant - initialInstant))
						nicThroughputDictionary[str(nicName)]['throughput'] += throughputSample
				exception = False
	
			#print nicThroughputDictionary['  eth0']['throughput']		
			sampleCount = sampleCount + 1
			sampleStart = False
			
	    for nicName in nicThroughputDictionary:
		#Evaluate the average throughput
	    	nicThroughputDictionary[str(nicName)]['throughput'] = float(nicThroughputDictionary[str(nicName)]['throughput'])/float(sampleCount-1)	
	    	#Evaluate the throughput in (bits/s)
	    	nicThroughputDictionary[str(nicName)]['throughput'] = (nicThroughputDictionary[str(nicName)]['throughput']*8)
	
	    #Prepares the dictionary to send
	    sendDictionary = {}
	
	    nicThroughputDictionaryCopy = copy.copy(nicThroughputDictionary)
	    for nicName in nicThroughputDictionaryCopy:
		if ( nicThroughputDictionary[str(nicName)]['updated'] != False ):
			sendDictionary[str(nicName)] = int(nicThroughputDictionary[str(nicName)]['throughput'])
		else:
			#Remove old entries
			del nicThroughputDictionary[str(nicName)]
	
	    #Pickles the dictionary
	    sendString = pickle.dumps(sendDictionary)
	   
	    
	  	
	    #For debug purposes
	
	    packetSize = 1470
	    header = 42
	    debugDictionary = pickle.loads(sendString)
	    for debugNic in debugDictionary:
		debugDictionary[str(debugNic)] = debugDictionary[str(debugNic)] * (float(packetSize)/float(packetSize + header))
		debugDictionary[str(debugNic)] = (float(debugDictionary[str(debugNic)]) / float(1024))/float(1024)
	    	print str(debugNic) + " " + str(debugDictionary[str(debugNic)])
		pass
	
	
	
	    #Send the information through the socket
	
	    try: 
		conn.send(sendString) 
	    except:
		connStatus = False
		#sys.exit(1)
	    	
	
	    #Mark all the entries as old
	    for nicName in nicThroughputDictionary:
	    	nicThroughputDictionary[str(nicName)]['updated'] = False

    


