// -*-	Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*-
/*
# Copyright (c) 2000-2001 by the University of Southern California.
# All rights reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation in source and binary forms for non-commercial purposes and
# without fee is hereby granted, provided that the above copyright notice
# appear in all copies and that both the copyright notice and this permission
# notice appear in supporting documentation, and that any documentation,
# advertising materials, and other materials related to such distribution and
# use acknowledge that the software was developed by the University of
# Southern California, Information Sciences Institute.  The name of the
# University may not be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THE UNIVERSITY OF SOUTHERN CALIFORNIA MAKES NO REPRESENTATIONS ABOUT THE
# SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  THIS SOFTWARE IS PROVIDED "AS
# IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
# LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE.
#
# Other copyrights might apply to parts of this software and are so noted when
# applicable.
# ----------------------------------------------------------------------------
#
# Primary author: Purushotham Kamath
#                 January 2001

#This material is based upon work supported by the Defense Advanced Research
#Projects Agency Information Technology Office, (NGI Multicast Applications 
#and Architecture (NMAA-ADDON), ARPA Order No. H645, Program Code No. 9A20, 
#Issued by DARPA/CMD under Contract No. MDA972-99-C-0022.
*/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

#include <eventhandler.h>
#include <packet.h>
#include <queue.h>
#include <component.h>
#include <scheduler.h>
#include <ipport.h>
#include <opport.h>
#include <debug.h>


extern Scheduler * sched;
extern int numIPPorts;
extern int numOPPorts;
extern OPPort **op;
extern IPPort **ip;




IPPort::IPPort(int qsize, char *ipfile): Component(qsize), pktcnt(0), portid(0) , numTotalPkts(0), numTotalBytes(0)
{
	fin = fopen(ipfile, "r");
	if (fin == NULL)
		dprintf("res.cc: IPPort::IPPort(): Could not open input file for reading\n");
	//Inputport delay: No delays on the input port, packets are scheduled as per their timestamp
	latency =0;
}

IPPort::~IPPort()
{
	fclose(fin);
}


//The data acquisition function of the IPPort: This function reads a 
//trace file, constructs a packet and processes it.
void IPPort::read()
{
	dprintf("res.cc: IPPort::read(): Entered function\n");
	

	double timestamp;
	int pktid;
	int srcaddr;
	int srcport;
	int dstaddr;
	int dstport;
	int size;
#ifdef TRACE_NSFORMAT
//Read event from trace file
	int f1, f2, f3, f4, flowid;
	char type[10];
	char flags[10];
	char r[10];
	if (fscanf(fin,  "%s %lf %d %d %s %d %s %d %d.%d %d.%d %d %d\n", r, &timestamp, &f1, &f2, type, &size, flags, &flowid, &srcaddr, &srcport, &dstaddr, &dstport, &f3, &pktid) == EOF)
#else
	if (fscanf(fin,  "%lf %d %d %d %d %d %d\n", &timestamp, &pktid,  &srcaddr, &srcport, &dstaddr, &dstport, &size) == EOF)
#endif
	{
		//sched->halt = 1;
		return;
	}
	numTotalPkts++;
	numTotalBytes+=size;
		


//Call ipport's processing function.
	latency = timestamp - sched->currenttime;
	dprintf("res.cc: IPPort::read(): Packetid: %d Dst addr: %d Size: %d\n", pktid, dstaddr, size);
	dprintf("res.cc: IPPort::read(): Current time: %.12f\n", sched->currenttime);
	dprintf("res.cc: IPPort::read(): Timestamp: %.12f\n", timestamp);
	dprintf("res.cc: IPPort::read(): Scheduling delay: %.12f\n", latency);
	
	Packet *packet = new Packet();
	packet->id = pktid;
	packet->ipport = portid;
	packet->opport = 0; //Default route 
	packet->altport = 0;
	packet->srcaddr = srcaddr;
	packet->dstaddr = dstaddr;
	packet->srcport = srcport;
	packet->dstport = dstport;
	packet->size = size;
	packet->timestamp = timestamp;
	process(packet);
}


//The event handling function of the IPPort. It dequeues a packet and
//sends it to the next component.
void IPPort::handleevent()
{
	dprintf("res.cc: IPPort::handleevent(): Entered function\n");
	

	//Pass it on to the next component in the path.
	Packet *p = queue->dequeue();
	dprintf("res.cc: IPPort::handleevent(): Packet id: %d\n", p->id);
	dprintf("res.cc: IPPort::handleevent(): Packet processing complete, passing it on to the next component.\n");
	Component::next->process(p);
	if(queue->head != NULL)
	{
		dprintf("res.cc: IPPort::handleevent(): Processing next packet in queue.\n");
		//Implements the processing time 
		state = BUSY;
		sched->scheduleevent(this);
	}
	else
	{
		dprintf("res.cc: IPPort::handleevent(): No more packets to process.\n");
		state = IDLE;
		read();
	}
}

void IPPort::dumpstats()
{
	printf("res.cc: IPPort::dumpstats():\n");
	printf("res.cc: IPPort::dumpstats(): Total number of packets(I/P): %d\n", numTotalPkts);
	printf("res.cc: IPPort::dumpstats(): Total number of bytes(I/P): %d\n", numTotalBytes);
	Component::dumpstats();
}

