Examples/IcmpFileTransfer/IcmpFileTransfer-pitcher.cpp
/**
 * Receive a file from the catcher
 */
Receive a file from the catcher
Receive a file from the catcher
void receiveFile(pcpp::IPv4Address pitcherIP, pcpp::IPv4Address catcherIP, int packetPerSec)
{
	pcpp::PcapLiveDevice* dev = pcpp::PcapLiveDeviceList::getInstance().getPcapLiveDeviceByIp(pitcherIP);
	if (dev == NULL)
		EXIT_WITH_ERROR("Cannot find network interface with IP '" << pitcherIP << "'");
	if (!dev->open())
		EXIT_WITH_ERROR("Cannot open network interface ");
	pcpp::MacAddress pitcherMacAddr = dev->getMacAddress();
	if (pitcherMacAddr == pcpp::MacAddress::Zero)
		EXIT_WITH_ERROR("Cannot find pitcher MAC address");
	double arpResTO = 0;
	pcpp::MacAddress catcherMacAddr = pcpp::NetworkUtils::getInstance().getMacAddress(catcherIP, dev, arpResTO, pitcherMacAddr, pitcherIP, 10);
	if (catcherMacAddr == pcpp::MacAddress::Zero)
		EXIT_WITH_ERROR("Cannot find catcher MAC address");
	uint16_t icmpId = 1;
	IcmpFileTransferStartRecv icmpFTStart = {
			pitcherIP,
			catcherIP,
			false,
			""
	};
	std::cout << "Waiting for catcher to start sending a file..." << std::endl;
	pcpp::ProtoFilter protocolFilter(pcpp::ICMP);
	if (!dev->setFilter(protocolFilter))
		EXIT_WITH_ERROR("Can't set ICMP filter on device");
	if (!dev->startCapture(waitForFileTransferStart, &icmpFTStart))
		EXIT_WITH_ERROR("Cannot start capturing packets");
	while (!icmpFTStart.gotFileTransferStartMsg)
	{
		sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_WAITING_FT_START, NULL, 0);
		icmpId++;
		pcpp::multiPlatformSleep(SEND_TIMEOUT_BEFORE_FT_START);
	}
	dev->stopCapture();
	std::ofstream file(icmpFTStart.fileName.c_str(), std::ios::out|std::ios::binary);
	if (file.is_open())
	{
		std::cout << "Getting file from catcher: '" << icmpFTStart.fileName << "' ";
		IcmpFileContentData icmpFileContentData = {
				pitcherIP,
				catcherIP,
				&file,
				icmpId,
				0,
				0,
				false,
				false
		};
		uint32_t sleepBetweenPackets = 0;
		if (packetPerSec > 1)
			sleepBetweenPackets = (uint32_t)(1000000UL / packetPerSec);
		if (!dev->startCapture(getFileContent, &icmpFileContentData))
		{
			file.close();
			EXIT_WITH_ERROR_AND_RUN_COMMAND("Cannot start capturing packets", std::remove(icmpFTStart.fileName.c_str()));
		}
		while (!icmpFileContentData.fileTransferCompleted && !icmpFileContentData.fileTransferError)
		{
			sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_WAITING_DATA, NULL, 0);
			if (packetPerSec > 1)
				usleep(sleepBetweenPackets);
			else if (packetPerSec == 1)
				pcpp::multiPlatformSleep(1);
			icmpId++;
		}
		dev->stopCapture();
		if (icmpFileContentData.fileTransferError)
		{
			for (int i = 0; i < NUM_OF_ABORT_MESSAGES_TO_SEND; i++)
			{
				sendIcmpRequest(dev, pitcherMacAddr, catcherMacAddr, pitcherIP, catcherIP, icmpId, ICMP_FT_ABORT, NULL, 0);
				usleep(SLEEP_BETWEEN_ABORT_MESSAGES);
			}
			file.close();
			EXIT_WITH_ERROR_AND_RUN_COMMAND("Sent abort message to catcher. Exiting...", std::remove(icmpFTStart.fileName.c_str()));
		}
		std::cout << std::endl << std::endl
			<< "Finished getting file '" << icmpFTStart.fileName << "' "
			<< "[received " << icmpFileContentData.fileSize << " bytes]"
			<< std::endl;
	}
	else
		EXIT_WITH_ERROR("Cannot create file");
	dev->close();
}
void receiveFile ( pcpp :: IPv4Address pitcherIP , pcpp :: IPv4Address catcherIP , int packetPerSec ) { pcpp :: PcapLiveDevice * dev = pcpp :: PcapLiveDeviceList :: getInstance ( ) . getPcapLiveDeviceByIp ( pitcherIP ) ; if ( dev == NULL ) EXIT_WITH_ERROR ( " " << pitcherIP << " " ) ; if ( ! dev -> open ( ) ) EXIT_WITH_ERROR ( " " ) ; pcpp :: MacAddress pitcherMacAddr = dev -> getMacAddress ( ) ; if ( pitcherMacAddr == pcpp :: MacAddress :: Zero ) EXIT_WITH_ERROR ( " " ) ; double arpResTO = 0 ; pcpp :: MacAddress catcherMacAddr = pcpp :: NetworkUtils :: getInstance ( ) . getMacAddress ( catcherIP , dev , arpResTO , pitcherMacAddr , pitcherIP , 10 ) ; if ( catcherMacAddr == pcpp :: MacAddress :: Zero ) EXIT_WITH_ERROR ( " " ) ; uint16_t icmpId = 1 ; IcmpFileTransferStartRecv icmpFTStart = { pitcherIP , catcherIP , false , " " } ; std :: cout << " " << std :: endl ; pcpp :: ProtoFilter protocolFilter ( pcpp :: ICMP ) ; if ( ! dev -> setFilter ( protocolFilter ) ) EXIT_WITH_ERROR ( " " ) ; if ( ! dev -> startCapture ( waitForFileTransferStart , & icmpFTStart ) ) EXIT_WITH_ERROR ( " " ) ; while ( ! icmpFTStart . gotFileTransferStartMsg ) { sendIcmpRequest ( dev , pitcherMacAddr , catcherMacAddr , pitcherIP , catcherIP , icmpId , ICMP_FT_WAITING_FT_START , NULL , 0 ) ; icmpId ++ ; pcpp :: multiPlatformSleep ( SEND_TIMEOUT_BEFORE_FT_START ) ; } dev -> stopCapture ( ) ; std :: ofstream file ( icmpFTStart . fileName . c_str ( ) , std :: ios :: out | std :: ios :: binary ) ; if ( file . is_open ( ) ) { std :: cout << " " << icmpFTStart . fileName << " " ; IcmpFileContentData icmpFileContentData = { pitcherIP , catcherIP , & file , icmpId , 0 , 0 , false , false } ; uint32_t sleepBetweenPackets = 0 ; if ( packetPerSec > 1 ) sleepBetweenPackets = ( uint32_t ) ( 1000000UL / packetPerSec ) ; if ( ! dev -> startCapture ( getFileContent , & icmpFileContentData ) ) { file . close ( ) ; EXIT_WITH_ERROR_AND_RUN_COMMAND ( " " , std :: remove ( icmpFTStart . fileName . c_str ( ) ) ) ; } while ( ! icmpFileContentData . fileTransferCompleted && ! icmpFileContentData . fileTransferError ) { sendIcmpRequest ( dev , pitcherMacAddr , catcherMacAddr , pitcherIP , catcherIP , icmpId , ICMP_FT_WAITING_DATA , NULL , 0 ) ; if ( packetPerSec > 1 ) usleep ( sleepBetweenPackets ) ; else if ( packetPerSec == 1 ) pcpp :: multiPlatformSleep ( 1 ) ; icmpId ++ ; } dev -> stopCapture ( ) ; if ( icmpFileContentData . fileTransferError ) { for ( int i = 0 ; i < NUM_OF_ABORT_MESSAGES_TO_SEND ; i ++ ) { sendIcmpRequest ( dev , pitcherMacAddr , catcherMacAddr , pitcherIP , catcherIP , icmpId , ICMP_FT_ABORT , NULL , 0 ) ; usleep ( SLEEP_BETWEEN_ABORT_MESSAGES ) ; } file . close ( ) ; EXIT_WITH_ERROR_AND_RUN_COMMAND ( " " , std :: remove ( icmpFTStart . fileName . c_str ( ) ) ) ; } std :: cout << std :: endl << std :: endl << " " << icmpFTStart . fileName << " " << " " << icmpFileContentData . fileSize << " " << std :: endl ; } else EXIT_WITH_ERROR ( " " ) ; dev -> close ( ) ; }
Receive a file from the catcher
Receive a file from the catcher
// identify the interface to listen and send packets to
 // try to open the interface (device)
 // get the MAC address of the interface
 // discover the MAC address of the catcher by sending an ARP ping to it
 // set an ICMP protocol filter so it'll capture only ICMP packets
 // since it's the pitcher's job to send ICMP requests and the catcher's job to get them and send ICMP replies,
 // sending a file from the catcher to the pitcher is a bit more complicated
 // so for start the pitcher needs the file name. It sends an ICMP request with ICMP_FT_WAITING_FT_START message in the timestamp field
 // and awaits for catcher response that should include the file name
 // start capturing ICMP packets. The waitForFileTransferStart callback should look for the catcher reply and set icmpFTStart.gotFileTransferStartMsg
 // to true
 // while didn't receive response from the catcher, keep sending the ICMP_FT_WAITING_FT_START message
 // sleep for a few seconds between sending the message
 // stop capturing packets
 // create a new file with the name provided by the catcher
 // the next thing to do is start getting the file data. For doing that the pitcher sends the catcher ICMP requests with message type
 // ICMP_FT_WAITING_DATA in the timestamp field. The catcher should send an ICMP response for each such request with data chunk of the
 // file
 // calculate how many microseconds (usec) the pitcher needs to sleep between sending the ICMP_FT_WAITING_DATA message
 // (calculated from user defined packetPerSec parameter).
 // The calculation is done in usec as in most cases the pitcher needs to sleep less than 1 second between chunks. However if packetPerSec
 // equals to 1 it means sleeping for 1 second and in this case we can't use usleep (as it's not working for 1 sec or more) and we use
 // sleep instead
 // start capturing ICMP packets. The getFileContent callback should look for the catcher replies containing data chunks of the file
 // and write them to the opened file. When catcher signals the end of the file transfer, the callback will set the
 // icmpFileContentData.fileTransferCompleted flag to true
 // keep sending ICMP requests with ICMP_FT_WAITING_DATA message in the timestamp field until all file was received or until an error occured
 // if rate limit was set by the user, sleep between sending packets
 // stop capturing packets
 // if an error occurred (for example: pitcher missed some of the file content packets), send several abort message to the catcher
 // so it'll stop waiting for packets, and exit the program
 // file transfer was completed successfully
 // close the device
