示例#1
0
文件: client.cpp 项目: mli9502/cs3516
//Data link layer function to receive a data frame or an ack from server.
//Also simulates the physical layer receive funtion.
//The data frame received contains an ack in its payload.
int dll_recv_py(int sock, Frame* frame, Ack* ack)
{
	//Set up the receive buffer.
	int size = 150;
	ssize_t numBytes = 0;
	char buffer[size];
	//Use recv() funtion to receive from server.
	numBytes = recv(sock, buffer, size, 0);
	vector<char> objBuf;
	for(int i=0; i<numBytes; i++)
	{
		objBuf.push_back(buffer[i]);
	}
	//Check the frame type field to determie whether it's a data frame or an ack.
	//If it's an ack, return 0, if it's a data frame, return 1.
	if(objBuf.at(2) == 'a')
	{
		Ack tempAck;
		*ack = tempAck.reconstruct(objBuf);
		return 0;
	}
	else
	{
		Frame tempFrame;
		*frame = tempFrame.reconstruct(objBuf);
		return 1;
	}
}
示例#2
0
//##############################################################################
//##############################################################################
bool
RequestQueueClient::request(const Request& req, Ack& ack)
{
    RANGE_LOG_TIMED_FUNCTION();
    if (! verify_request(req)) {
        throw MqueueException("invalid request");
    }

    ack_queue.flush(); /* Ensure ack queue is empty; ack_queue is specific for this thread
                          so we should be the only consumer; any garbage left in the 
                          ack_queue is from a previously expired request */

    if (! sending_queue.send(req.SerializeAsString())) {
        return false;
    }
    std::string ack_payload = ack_queue.receive();
    if (ack_payload.size() > 0) {
        if(! ack.ParseFromString(ack_payload)) {
            return false;
        }
        if(ack.request_id() != req.request_id()) {
            return false;
        }
        if(ack.client_id() != req.client_id()) {
            return false;
        }
        return true;
    }
    return false;
}
int main(int _argc, char *_argv[]) {
  /*
  Frame f(69, 'A');
  cout << f.isValid() << endl;
  cout << f.getFrameNumber() << endl;
  cout << f.getData() << endl;
*/
/*
  Byte* packet = f.serialize();
  Frame a;
  a.unserialize(packet);
  cout << a.isValid() << endl;
  cout << a.getFrameNumber() << endl;
  cout << a.getData() << endl;
*/
  Ack a(4, 69);
  cout << a.isValid() << endl;
  cout << a.getFrameNumber() << endl;
  cout << a.getAck() << endl;
  Byte * b = a.serialize();

  Ack c;
  c.unserialize(b);
  cout << c.isValid() << endl;
  cout << c.getFrameNumber() << endl;
  cout << c.getAck() << endl;
  return 0;
}
示例#4
0
int main()
{
	int b;
	Ack a;

	b = a.Run ( 3 ,12 );
}
示例#5
0
bool read_ack( Ack ack, google::protobuf::io::CodedInputStream& codedInput ){
	//TODO: use exception.
	unsigned int ack_size;
	codedInput.ReadVarint32( &ack_size );
	cout<<"ack size recorded as "<< ack_size << endl ;
	int limit = codedInput.PushLimit( ack_size );
	bool ack_parse_ret = ack.ParseFromCodedStream(&codedInput);
	codedInput.PopLimit( limit );
	if( false == ack_parse_ret ){
		cerr<<"parse response error" <<endl;
		return false;
	}
	if(not ack.success()){
		return false;
	}
	else{
		return true;
	}
}
void* childProcessACK(void *threadid) {
	// child process
	// receive ACK/NAK from receiver
	struct sockaddr_in srcAddr;
	socklen_t srcLen;
	printf("masuk thread\n");

	char* serializedAck;

	 while (isSocketOpen) {
		printf("proses\n");
		if (recvfrom(sockfd, serializedAck, 4, 0, (struct sockaddr *) &srcAddr, &srcLen) != sizeof(Ack))
			error("ERROR: recvfrom() receive buffer with size more than expected.\n");

		Ack *ack = new Ack(serializedAck);
		int i=0;
		while (i<WINSIZE) {
			if (window.getFrameBuffer().getElement((window.getFrameBuffer().getHead()+i)%WINSIZE).getNo() == ack->getFrameNo())
				break;
			else
				i++;
		}

		if (ack->getAck()==ACK) {
			printf("Received ACK for Frame No: %d\n",ack->getFrameNo());
			window.setAckTrue((window.getFrameBuffer().getHead()+i)%WINSIZE);
			received++;
		} else if (ack->getAck()==NAK) {
			printf("Received NAK for Frame No: %d\n",ack->getFrameNo());
			if (sendto(sockfd, window.getFrameBuffer().getElement(i).getSerialized(), window.getFrameBuffer().getElement(i).getSize(), 0, (const struct sockaddr *) &receiverAddr, sizeof(receiverAddr)) != window.getFrameBuffer().getElement(i).getSize())
					error("ERROR: sendto() sent buffer with size more than expected.\n");
			printf("Sending frame no. %d: %s\n", window.getFrameBuffer().getElement(i).getNo(), window.getFrameBuffer().getElement(i).getData());
			window.setTimeOut(i);
		}		
	} 

	pthread_exit(NULL);
}
示例#7
0
文件: client.cpp 项目: mli9502/cs3516
//Data link layer function to send Ack data frame to network layer.
//Also simulates the check in network layer.
int dll_send_nwl(Frame frame, bool* breakFlg, int seqNum, bool ieop)
{
	//Get the ack from the data frame.
	Ack ack;
	ack = ack.reconstruct(frame.getDataField());
	//If the ack is correct.
	if(ack.reconstruct(frame.getDataField()).isCorrect(seqNum))
	{
		//If this frame is the end of photo, set the break flag.
		if(ieop)
		{
			*breakFlg = true;
		}
		nwl = true;
		dll = false;
		return 1;
	}
	//If the ack is not correct, return -1.
	else
	{
		return -1;
	}
}
示例#8
0
文件: client.cpp 项目: mli9502/cs3516
int main(int argc, char** argv)
{
	//Get the started time and create a logfile.
	struct timeval tv_s, tv_e;
	gettimeofday(&tv_s, NULL);
	time_t now = tv_s.tv_sec;
	struct tm *pstart = localtime(&now);
	string olog;
	logname = string("client_") + *argv[2] + ".log";
	outputfile.open(logname.c_str());
	outputfile  << timeToString(pstart) << ":" <<setfill('0') << setw(3) << tv_s.tv_usec/1000 << "	" << "Process  started" << endl;
	outputfile.close();

	//
	//Define a input file stream for reading in photos.
	ifstream photo;
	//Check for command line arguments.
	if(argc != 4)
	{
		cout << "Command line argument not correct!" << endl;
		exit(-1);
	}
	//Get the client id number and the client photo count.
	int id = atoi(argv[2]);
	int numPhotos = atoi(argv[3]);
	//Defines the socket descriptor.
	int sockDscp;
	//Calls the physical layer connect function to establish connection with server.
	sockDscp = py_connect(argv[1]);
	//Transport all the given photos.
	for(int np=0; np<numPhotos; np++)
	{
		//Open the photo.
		string name = "photo" + toString(id) + toString(np + 1) + ".jpg";
		photo.open(name.c_str());
		//log: opend the photo
		olog = "Opened " + name;
		outputToLog(olog.c_str());
		//Set the network layer flag to true and data link layer flag to false
		//since network layer will start reading in packets first.
		nwl = true;
		dll = false;
		while(true)
		{
			//Break flag to break out the while loop when one photo is finished transmitting. 
			bool breakFlg = false;
			//Defines the variables used by select function.
			fd_set readfds;
			struct timeval tv;
			//Initialize the fd_set and the timer interval.
			FD_ZERO(&readfds);
			FD_SET(sockDscp, &readfds);
			tv.tv_sec = 0;
			tv.tv_usec = 250000;	
			//Start the network layer if network layer flag is true.
			if(nwl)
			{
				//Read 256 bytes data from the photo.
				char buffer[256];
				char eop = 0;
				memset(buffer, 0, 256);
				photo.read(buffer, 256);
				//Check whether the read has 256 bytes of data.
				//If not, get the number of bytes that are read in.
				int rtn;
				if(photo)
				{
					rtn = 256;
				}
				else
				{
					rtn = photo.gcount();
				} 
				//Construct a packet from the data reading in.
				vector<char> chunkBuf;
				for(int i=0; i<rtn; i++)
				{
					chunkBuf.push_back(buffer[i]);
				}
				Packet pkt(chunkBuf);
				//If the data read in is not 256 bytes, set this packet as the end of photo.
				if(rtn != 256)
				{
					pkt.setEndofPhoto();
				}				
				//Send the packet to data link layer.
				olog = "Packet is sent to the datalink layer ";
				outputToLog(olog.c_str());
				totalPktCnt ++;
				nwl_send(pkt);
			}
			//Start the data link layer if data link layer flag is true.
			else if(dll)
			{	
				//Get the frames from the packet.			
				vector<Frame> frames = dataLink.splitPacket();
				//Transfer all the frames to server.
				for(int i=0; i<frames.size(); i++)
				{
					//Defines the frame that is going to be sent.
					Frame send_frame = frames.at(i);
					//Record the sequence number to check the ack frame latter.
					int seqNum = send_frame.getSeq();
					//Set end of photo indicator.
					bool ieop = frames.at(i).isEndofPhoto();
					//Generating an error frame every 6 frames.
					if(totalFrameCnt % 6 == 0)
					{	
						send_frame = send_frame.generateErrorFrame();
					}
					//Send this frame through physical layer.
					dll_send_py(send_frame, sockDscp);
					totalNumFramesSent ++;
					olog = "Frame sent for frame " + toString(frames.at(i).getSeq()) + " of packet " + toString(totalPktCnt);
					outputToLog(olog.c_str());
					//Defines the received frame or receive ack.
					Frame recvFrame;
					Ack recvAck;			
					while(1)
					{
						//Using select funtion to set up the timer.
						int rtnVal = select(sockDscp + 1, &readfds, NULL, NULL, &tv);					
						if(rtnVal < 0)
						{
							cout << "select error" << endl;
							exit(-1);
						}
						//If the socket receives data.
						else if(rtnVal > 0 && FD_ISSET(sockDscp, &readfds))
						{
							//Call the data link layer receive funtion to receive data from physical layer.
							//Checks the return value of this funtion to determin wheter the receive data
							//represents a data frame or an ack.
							int drpRtn = dll_recv_py(sockDscp, &recvFrame, &recvAck);
							//If the received data is a data frame.
							if(drpRtn)
							{
								//Check whether the received data frame is correct by sending it to network layer.
								if(recvFrame.isCorrect())
								{
									int rtn = dll_send_nwl(recvFrame, &breakFlg, seqNum, ieop);
									//If the ack packet contained in the received data frame is correct,
									//reset the timer and send the next frame. 
									//If not, keeps waiting for timeout to retransmit.
									if(rtn == 1)
									{
										olog = "Ack frame received successfully for frame " + toString(frames.at(i).getSeq()) + " of packet " + toString(totalPktCnt);
										totalNumGoodAcks ++;
										outputToLog(olog.c_str());
										FD_ZERO(&readfds);
										FD_SET(sockDscp, &readfds);
										tv.tv_sec = 0;
										tv.tv_usec = 250000;
										break;
									}
									else
									{
										olog = "Ack frame received in error for frame " + toString(frames.at(i).getSeq()) + " of packet " + toString(totalPktCnt);
										outputToLog(olog.c_str());
										totalNumErrorAcks ++;
									}
								}								
							}
							//If the received data is an ack.
							else
							{
								//If the received ack is correct, reset the timer and send the next frame.
								//If not, keeps waiting for timeout to retransmit.
								if(recvAck.isCorrect(seqNum))
								{
									olog = "Ack packet received successfully for frame " + toString(frames.at(i).getSeq()) + " of packet " + toString(totalPktCnt);
									totalNumGoodAcks ++;
									outputToLog(olog.c_str());
									FD_ZERO(&readfds);
									FD_SET(sockDscp, &readfds);
									tv.tv_sec = 0;
									tv.tv_usec = 250000;
									break;
								}
								else
								{
									olog = "Ack packet received in error for frame " + toString(frames.at(i).getSeq()) + " of packet " + toString(totalPktCnt);
									outputToLog(olog.c_str());
									totalNumErrorAcks ++;
								}
							}							
						}
						//If the timer expires.
						else
						{
							olog = "Timer was expired";
							outputToLog(olog.c_str());
							//Retransmit the correct frame by physical layer.
							dll_send_py(frames.at(i), sockDscp);
							totalNumFramesRetrans ++;
							totalNumFramesSent ++;
							olog = "Frame resent for frame " + toString(frames.at(i).getSeq()) + " of packet " + toString(totalPktCnt);
							outputToLog(olog.c_str());
							//Reset the timer and waiting for server side ack.
							tv.tv_sec = 0;
							tv.tv_usec = 250000;
							FD_ZERO(&readfds);
							FD_SET(sockDscp, &readfds);
							continue;
						}
					}
					//Increase the total frame count after sending a frame.
					//The the retransitted frames are not counted when simulating the error.
					totalFrameCnt ++;
				}
				//If the break flag is set, break out the while loop and send the next photo.
				if(breakFlg)
				{
					break;
				}
			}
		}
		//Close the photo after sending it and reset the total packet count.
		photo.close();
		totalPktCnt = 0;
		olog = "Closed " + name;
		outputToLog(olog.c_str());
        outputfile.open(logname.c_str(),  ios::app);
		//Output the statistics.
        outputfile << "The total number of frames sent (including retransmitted frames) is " << toString(totalNumFramesSent) << endl;
        outputfile << "The total number of frames retransmitted is " << toString(totalNumFramesRetrans) << endl;
        outputfile << "The total number of good ACKs (including good Ack and good data frame including ack) received is " << toString(totalNumGoodAcks) << endl;
        outputfile << "The total number of error ACKs (including error Ack and data frame including error ack) received is " << toString(totalNumErrorAcks) << endl;
        totalNumErrorAcks = 0;
        totalNumGoodAcks = 0;
        totalNumFramesRetrans = 0;
        totalNumFramesSent = 0;
        outputfile.close();
    }
	//Close the socket after sending all the photos.
	close(sockDscp);
	gettimeofday(&tv_e, NULL);
	now = tv_e.tv_sec;
	struct tm *pend = localtime(&now);
	outputfile.open(logname.c_str(),  ios::app);
	int milisec = ((tv_e.tv_sec - tv_s.tv_sec) * 1000 + (tv_e.tv_usec - tv_s.tv_usec) / 1000);
	string executiontime =toString(milisec/1000/60)+"m"+toString(milisec/1000%60) +"s"+ toString(milisec % 1000) + "ms";
	outputfile  << timeToString(pend) << ":" <<setfill('0') << setw(3) << tv_e.tv_usec/1000 << "	" << "Process ended"<< endl;	
	outputfile <<"The total exectution time is "<< executiontime << endl;
	outputfile.close();
}
示例#9
0
//##############################################################################
//##############################################################################
bool
RequestQueueListener::send_ack(const std::string &client_id, const Ack &ack)
{
    MessageQueue<> ackq { CreateMQ(ack_queue_prefix + client_id), cfg_->reader_ack_timeout(), 1000 };
    return ackq.send(ack.SerializeAsString());
}
示例#10
0
void waitForMessages()
{
	// Turn off the timeout.
	Serial.setTimeout(100);
	
	// Ack for packet that hasn't been sent.
	RxIdentify* rxIdentify = new RxIdentify();
	rxIdentify->setRandom0(0);
	rxIdentify->setRandom1(0);
	rxIdentify->setSeqNr(1);
			
	Ack* rxAck = new Ack();
	rxAck->setSeqNr(1);
	
	boolean wasMessageRcvd = false;
	unsigned char *bytes = new unsigned char [TX_SIZE];
	while(true)
	{
		for(int i = 0; i < TX_SIZE; i++)
			bytes[i] = (unsigned char) 0;
	
		wasMessageRcvd = readTxMessage(bytes);
		// If the first message was received, and it is a TX_IDENTIFY.
		if(wasMessageRcvd) {
			TxIdentify* txIdentify = new TxIdentify(bytes); 
			Note* note = new Note(bytes);
			Pause* pause = new Pause(bytes);
			ToneTime* toneTime = new ToneTime(bytes);
			NoToneTime* noToneTime = new NoToneTime(bytes);
			switch(bytes[TX_INFO_0])
			{
				case TX_IDENTIFY:
					if(txIdentify->getSeqNr() == expected_seq_nr)
					{
						// Set the acknowledgement packet.
						rxIdentify->setRandom0((unsigned char)((txIdentify->getRandom0() + 1) % 256));
						rxIdentify->setRandom1((unsigned char)((txIdentify->getRandom1() + 1) % 256));
						rxIdentify->setSeqNr(txIdentify->getSeqNr());
					}
					break;
				case PAUSE:
					if(pause->getSeqNr() == expected_seq_nr)
					{
						// Set the acknowledgement packet.
						rxAck->setSeqNr(pause->getSeqNr());
					}
					break;
				case NOTE:
					if(note->getSeqNr() == expected_seq_nr)
					{
						// Set the acknowledgement packet.
						rxAck->setSeqNr(note->getSeqNr());
						double a = pow(2.0, 1.0 / 12.0);
						int t = (int) (pow(a, (double) ((int)(note->getStep()) - 57)) * 440.0);
						if(t < 30)
							t = 30;
						else if(t > 3000)
							t = 3000;
						tone(note->getPin(), t, 100);
					}
					break;
				case TONE_TIME:
					if(toneTime->getSeqNr() == expected_seq_nr)
					{
						// Set the acknowledgement packet.
						rxAck->setSeqNr(toneTime->getSeqNr());
					}
					break;
				case NO_TONE_TIME:
					if(noToneTime->getSeqNr() == expected_seq_nr)
					{
						// Set the acknowledgement packet.
						rxAck->setSeqNr(noToneTime->getSeqNr());
					}
					break;
			}
			
			delete txIdentify; 
			delete pause;
			delete note;
			delete noToneTime;
			delete toneTime;
		}
		
		RxMessage* rxMessage;
		rxMessage = bytes[TX_INFO_0] == TX_IDENTIFY ? ((RxMessage*) rxIdentify) : ((RxMessage*) rxAck);
		if(writeRxMessage(rxMessage->getBytes()) && wasMessageRcvd)
			expected_seq_nr = expected_seq_nr ? 0 : 1;
	}
	
	delete rxIdentify;
	delete rxAck;
}
示例#11
0
void GetResponse::action() const { // Process response file
/* This should be scheduled after an Upload and dshould be repeated every minute
  until a download.1.done file exists.
  It is not an error for there to be no download.1.xml file
  If it does exist it is renamed to download.1.xml.done, which will eventually be overwritten
  but does help with seeing what has been going on
  
  Also see if there is an ack.xml file. If so, read it an adjust lastupload if required.
*/
	Response r;
	string responsefile("/tmp/download.");
	char siteno[20];
	string buf;
	if (conf.getSiteId() < 0)		// Deal with unconfigured site by using MAC as siteno.
		strcpy(siteno, getmac());
	else
		sprintf(siteno, "%d", conf.getSiteId());
	responsefile += siteno;
	string donefile(responsefile);
	responsefile += ".xml";		// download.$site.xml
	donefile += ".done";		// download.$site.done
	DEBUG cerr << "GetResponse::action File " << responsefile << " Donefile " << donefile << endl;
	if (r.stat(donefile)) {
		DEBUG cerr << "Found .done file .. trying .xml";
		if (r.stat(responsefile)) {
			if (rename(responsefile.c_str(), donefile.c_str()) == -1) {
				buf = "event WARN failed to rename " + responsefile + " to " + donefile;
				cerr << buf;
				journal.add(new Message(buf));
			}
			else {
				r.read(donefile);	// this parses and adds to queue.
				DEBUG cerr << "Processing " << responsefile << endl;
			}
			// We do this AFTER renaming it in case it causes MCP to crash and restart on the same file
			
			DEBUG cerr << "GetResponse::action renamed " << responsefile.c_str() << " to " << donefile.c_str() << endl;
		}	
		else
			DEBUG cerr << " No .xml file. Not retrying\n";
			
		// Now look for ack.xml
		string ackfile("/tmp/ack.");
		ackfile += siteno;
		ackfile += ".xml";
		Ack ack;
		DEBUG cerr << "Looking for " << ackfile << " ";
		if (ack.stat(ackfile)) {
			DEBUG cerr << "Found " << ackfile;
			ack.read(ackfile);
			if (ack.lastProcessed) {
				if (ack.lastProcessed + var.processLag < var.lastUpload) {
					DEBUG { Timestamp t1(var.lastUpload);
						Timestamp t2(ack.lastProcessed);
						buf = "event INFO Ack: Resetting LastUpload from ";
						buf += t1.getTime();
						buf += " to ";
						buf += t2.getTime();
						journal.add(new Message(buf));
					}
					var.lastUpload = ack.lastProcessed;
					var.lastProcessed = ack.lastProcessed;
				}
				else