Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

БВТ1803 Пинг Код Подгруппа 1

.pdf
Скачиваний:
15
Добавлен:
18.05.2021
Размер:
335.33 Кб
Скачать

#define DEBUG

//define debug log

#ifdef DEBUG

 

#define LOGD(MSG) std::cout<<MSG<<std::endl;

 

#else

 

#define LOGD(MSG)

 

#endif

 

 

//LIBRARY DECLARATION

 

//

#include <string_view>

//string library

#include <regex>

//regex library

#include <chrono>

//time library

#include <filesystem>

//library for working with file system

#include <fstream>

//library to file work

#include <iostream>

//console output library

#include <errno.h>

//library for fileerror cath

#include "winsock2.h"

//socket library

#include "iphlpapi.h"

//some library for net

#include "icmpapi.h"

//icmp library

 

//DECLARATION OF GLOBAL VARIABLES

 

//

uint32_t errorCode,

//Error code

fErrorCode,

//File error code

countOfEchoRequest;

//Number of echo requests

std::string_view pathToLogFile;

//Path to the log file

char* innerBuffer;

//Data buffer

 

//Link library

#pragma comment(lib, "IPHLPAPI.lib")

//link icmpapi

#pragma comment(lib, "Ws2_32.lib")

//link winsock2

 

//FUNCTION DECLARATION

 

//

bool checkParams(int countOfArgs,char* args[])

//Checking input parameters

{

 

LOGD("Enter in " << __func__ << " errorCode =" <<

 

errorCode << " CountOfArgs =" << countOfArgs);

//DEBUG MESSAGE

#ifdef DEBUG

 

if (countOfArgs > 1)

 

LOGD(" Addr =" << args[1]);

 

for (size_t i = 0; i < countOfArgs; i++)

 

LOGD(" el =" << args[i]);

 

#endif

 

if (countOfArgs != 2)

//accept only one extra argument - IPV4

errorCode = 3;

 

else if (!std::regex_match(*(args + 1),

//check IPV4 format - from 0.0.0.0 to 255.255.255.255

std::regex{ "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$" }))

errorCode = 4;

 

LOGD("Leave " << __func__ << " errorCode =" << errorCode );

//DEBUG MESSAGE

return errorCode != 0;

 

}

 

std::string paramError(char** argc)

//Definition param error

{

 

LOGD("Enter in " << __func__ << " errorCode ="<<errorCode);

//DEBUG MESSAGE

std::string result;

//Create empty resulg info

switch (errorCode)

//Definition error

{

 

case 3:

 

result= std::to_string(errorCode)+ " Wrong count of args";

 

break;

 

case 4:

 

result = argc[1];

 

result +=' ' + std::to_string(errorCode) + " Wrong IP format";

 

break;

 

default:

 

result = std::to_string(errorCode) + " Unknown Error";

 

break;

 

}

 

LOGD("Leave " << __func__ << " Result =" << result);

//DEBUG MESSAGE

return result;

 

}

 

bool checkLog()

/*Checking the existence of a

 

log file*/

{

 

LOGD("Enter in " << __func__);

//DEBUG MESSAGE

LOGD("Leave " << __func__ << " Result =" << !std::filesystem::exists(pathToLogFile));

return !std::filesystem::exists(pathToLogFile);

//check log

}

 

bool logFileCreate()

//Create log file

{

 

LOGD("Enter in " << __func__ << " fErrorCode =" << fErrorCode);

//DEBUG MESSAGE

std::ofstream fStream(pathToLogFile);

//Create new log file

if (fStream.fail())

 

fErrorCode = errno;

//If error - save error code

fStream.close();

 

//DEBUG MESSAGE LOGD("Leave " << __func__ << " fErrorCode =" << fErrorCode << " Result=" << (fErrorCode != 0)); return fErrorCode!=0;

}

 

void LOGFILE_DIAGNOSTIC_ERROR()

//Diagnosing a log error

{

 

LOGD("Enter in " << __func__ << " fErrorCode =" <<fErrorCode);

//DEBUG MESSAGE

std::string result;

//Create empty resulg info

result = std::to_string(fErrorCode);

 

switch (fErrorCode)

//Definition error

{

 

case EPERM:

 

result.append(" The operation is not allowed");

 

break;

 

case ENOENT:

 

result.append(" There is no such file or directory.");

 

break;

 

case EBADF:

 

result.append(" Bad file descriptor.");

 

break;

 

case EACCES:

 

result.append(" Permission denied.");

 

break;

 

case EBUSY:

 

result.append(" The device or resource is busy");

 

break;

 

case EEXIST:

 

result.append(" The file exists.");

 

break;

 

case EXDEV:

 

result.append(" Invalid communication between devices.");

 

break;

 

case EMFILE:

 

result.append(" There are too many open files.");

 

break;

 

case ENFILE:

 

result.append(" There are too many open files in the system");

 

break;

 

case ETXTBSY:

 

result.append(" The text file is busy.");

 

break;

 

case EFBIG:

 

result.append(" The file is too large.");

 

break;

 

case ENOSPC:

 

result.append(" There is no free space left on the device.");

 

break;

 

case EROFS:

 

result.append(" The file system is read-only.");

 

break;

 

default:

 

result.append(" Unknown Error");

 

break;

 

}

 

std::cout << result << std::endl;

 

LOGD("Leave " << __func__ << " Result ="<<result);

//DEBUG MESSAGE

}

/*Adding information to the log*/

bool addIntoLogFile(std::string_view output = "",char** ip = nullptr)

{

//DEBUG MESSAGE

LOGD("Enter in " << __func__ << " Input string ='" << output << "' errorCode =" << errorCode << " fErrorCode =" << fErrorCode);

std::time_t t;

//Create base time struct

std::tm* now;

//Create advance time struct

std::ostream* ostr;

//pointer to ofstream/cout

std::time(&t);

 

now = std::localtime(&t);

 

std::ofstream fStream(pathToLogFile,

 

std::ios::out | std::ios::ate | std::ios::_Nocreate);

//try to open file

ostr = &fStream;

 

if (fStream.fail())

//if smt wrong

{

 

fErrorCode = errno;

//save error

ostr = &std::cout;

//change outputStream to cout

*ostr << "LOG ERROR\n";

 

}

 

 

//outprint msg

*ostr << '[' << now->tm_hour << ':' << now->tm_min << ':' << now->tm_sec << "] ";

if (ip)

//if we have ip - add

*ostr << ip[1] << ' ';

 

*ostr << output.data() << '\n';

 

fStream.close();

 

LOGD("Leave " << __func__ << " Input string ='" << output << "' errorCode =" //DEBUG MESSAGE << errorCode << " fErrorCode =" << fErrorCode << " Result =" << (fErrorCode != 0));

return fErrorCode!=0;

}

int echoRequest(std::string_view address)

//Echo request

{

 

 

//DEBUG MESSAGE

LOGD("Enter in " << __func__ << "Address ='" << address << "' errorCode =" << errorCode);

HANDLE hIcmpFile;

//Build echo-request

unsigned long ipaddr;

//create destination addr

uint64_t countOfAnswers, replySize;

//count of answers and reply buffer size

char sendData[32];

//send data

std::size_t innerCounter;

//number of requests made

ipaddr = inet_addr(address.data());

 

countOfAnswers = innerCounter = 0;

 

replySize = sizeof(ICMP_ECHO_REPLY) + sizeof(sendData);

 

hIcmpFile = IcmpCreateFile();

//create a handler

innerBuffer = new char[replySize];

//take memory

do

//try to send request

{

 

countOfAnswers = IcmpSendEcho(hIcmpFile, ipaddr, sendData, sizeof(sendData),NULL, innerBuffer, replySize, 1000); ++innerCounter;

}
std::cout << "Timeout exceeded" << std::endl; } while (innerCounter != countOfEchoRequest);
if (!countOfAnswers)
errorCode = GetLastError();

if (countOfAnswers)

//If no answer

{

 

LOGD("Leave " << __func__ << " Address =" << address

//DEBUG MESSAGE

<< " errorCode =" << errorCode << " Result =" << 0

 

return 0;

 

//save errorcode //DEBUG MESSAGE

LOGD("Leave " << __func__ << " Address =" << address << " errorCode =" << errorCode << " Result =" << (errorCode == IP_REQ_TIMED_OUT ? 2 : 1));

return (errorCode == IP_REQ_TIMED_OUT ? 2 : 1);

}

 

 

std::string echoError()

 

/*Handling response/request

 

 

error*/

{

 

 

LOGD("Enter in " << __func__ << " errorCode =" << errorCode);

//DEBUG MESSAGE

std::string result;

//Create empty resulg info

result = std::to_string(errorCode) + " ";

 

switch (errorCode)

 

//Definition error

{

 

 

case IP_DEST_NET_UNREACHABLE:

 

result= "The destination network was unreachable";

 

break;

 

 

case IP_DEST_HOST_UNREACHABLE:

 

result +=

"The destination host was unreachable";

 

break;

 

 

case IP_DEST_PROT_UNREACHABLE:

 

result +=

"The destination protocol was unreachable";

 

break;

 

 

case IP_DEST_PORT_UNREACHABLE:

 

result +=

"The destination port was unreachable";

 

break;

 

 

case IP_NO_RESOURCES:

 

result +=

"Insufficient IP resources were available";

 

break;

 

 

case IP_BAD_OPTION:

 

result +=

"A bad IP option was specified";

 

break;

 

 

case IP_HW_ERROR:

 

 

result +=

"A hardware error occurred";

 

break;

 

 

case IP_PACKET_TOO_BIG:

 

result +=

"The packet was too big";

 

break;

 

 

case IP_BAD_REQ:

 

 

result +=

"A bad request";

 

break;

 

 

case IP_BAD_ROUTE:

 

 

result +=

"A bad route";

 

break;

 

 

case IP_TTL_EXPIRED_TRANSIT:

 

result +=

"The time to live (TTL) expired in transit";

 

break;

 

 

case IP_TTL_EXPIRED_REASSEM:

 

result +=

"The time to live expired during fragment reassembly";

 

break;

 

 

case IP_SOURCE_QUENCH:

 

result +=

"Datagrams are arriving too fast to be processed and datagrams may have been discarded";

break;

 

 

case IP_BAD_DESTINATION:

 

result +=

"A bad destination";

 

break;

 

 

case IP_GENERAL_FAILURE:

 

result +=

"A general failure. This error can be returned for some malformed ICMP packets";

break;

 

 

default:

 

 

result +=

"Unknown error";

 

break;

 

 

}

 

 

LOGD("Leave " << __func__ << " Result =" << result);

//DEBUG MESSAGE

return result;

 

 

}

 

 

bool echoResponse(std::string& result)

//Echo response

{

 

 

LOGD("Enter in " << __func__ << " errorCode =" << errorCode );

//DEBUG MESSAGE

result = "Answer from : ";

//Create answer string

PICMP_ECHO_REPLY pEchoReply;

//echo-reply struct

struct in_addr ReplyAddr;

 

pEchoReply = (PICMP_ECHO_REPLY)innerBuffer;

 

ReplyAddr.S_un.S_addr = pEchoReply->Address;

 

if (!(errorCode = pEchoReply->Status))

//check response status

{

 

 

result.append(inet_ntoa(ReplyAddr));

//create output message

result.append(" count of byte = " + std::to_string(pEchoReply->DataSize)); result.append(" response time = " + std::to_string(pEchoReply->RoundTripTime) + "ms"); result.append(" TTL = " + std::to_string(pEchoReply->Options.Ttl));

std::cout << result << std::endl;

}

//DEBUG MESSAGE LOGD("Leave " << __func__ << " errorCode =" << errorCode << " Result =" << (errorCode != 0)); return errorCode!=0;

}

//Program's body

void main(int argv, char* argc[])

{

LOGD("Enter in " << __func__ << " argv =" << argv);

//DEBUG MESSAGE

std::string resultMSG;

//Create string for answer

resultMSG = "";

 

countOfEchoRequest = 2;

 

pathToLogFile = "C:\\Ping\\Log.txt";

 

fErrorCode = errorCode = 0;

 

innerBuffer = nullptr;

 

switch (checkParams(argv, argc))

 

{

 

 

//Correct parameter

case 0:

 

switch (checkLog())

 

{

 

 

//If log file exist

case 0:

 

switch (echoRequest(argc[1]))

 

{

 

case 2:

//end of cycle

switch (addIntoLogFile(std::to_string(errorCode) + " The request timed out", argc))

{

//Successful add info

case 0:

 

LOGD("Leave " << __func__);

//DEBUG MESSAGE

delete[] innerBuffer;

 

return;

//Failed to add info

case 1:

 

LOGFILE_DIAGNOSTIC_ERROR();

 

LOGD("Leave " << __func__);

//DEBUG MESSAGE

delete[] innerBuffer;

 

return;

 

}

 

case 0:

//Successful package dispatch

switch (echoResponse(resultMSG))

 

{

 

case 0:

 

switch (addIntoLogFile(resultMSG, argc))

 

{

//Successful add info

case 0:

 

LOGD("Leave " << __func__);

//DEBUG MESSAGE

delete[] innerBuffer;

 

return;

//Failed to add info

case 1:

 

LOGFILE_DIAGNOSTIC_ERROR();

 

LOGD("Leave " << __func__);

//DEBUG MESSAGE

delete[] innerBuffer;

 

return;

 

}

 

case 1:

 

switch (addIntoLogFile(echoError(),argc))

 

{

 

 

//Successful add info

case 0:

 

LOGD("Leave " << __func__);

//DEBUG MESSAGE

delete[] innerBuffer;

 

return;

 

 

//Failed to add info

case 1:

 

LOGFILE_DIAGNOSTIC_ERROR();

 

LOGD("Leave " << __func__);

//DEBUG MESSAGE

delete[] innerBuffer;

 

return;

 

}

 

}

 

case 1:

//Failed package dispatch

switch (addIntoLogFile(echoError(), argc))

 

{

 

 

//Successful add info

case 0:

 

LOGD("Leave " << __func__);

//DEBUG MESSAGE

delete[] innerBuffer;

 

return;

 

 

//Failed to add info

case 1:

 

LOGFILE_DIAGNOSTIC_ERROR();

 

LOGD("Leave " << __func__);

//DEBUG MESSAGE

delete[] innerBuffer;

 

return;

 

}

 

}

//If log file doesnt exist

case 1:

 

switch (logFileCreate())

 

{

 

case 0:

 

switch (echoRequest(argc[1]))

 

{

 

case 2:

//end of cycle

switch (addIntoLogFile(std::to_string(errorCode) + " The request timed out", argc))

{

//Successful add info

case 0:

 

LOGD("Leave " << __func__);

//DEBUG MESSAGE

delete[] innerBuffer;

 

return;

 

case 1:

//Failed to add info

LOGFILE_DIAGNOSTIC_ERROR();

 

LOGD("Leave " << __func__);

//DEBUG MESSAGE

delete[] innerBuffer;

 

return;

 

}

 

case 0:

switch (echoResponse(resultMSG))

{

case 0:

switch (addIntoLogFile(resultMSG, argc))

{

case 0:

LOGD("Leave " << __func__); delete[] innerBuffer; return;

case 1:

LOGFILE_DIAGNOSTIC_ERROR(); LOGD("Leave " << __func__); delete[] innerBuffer; return;

}

case 1:

switch (addIntoLogFile(echoError(), argc))

{

case 0:

LOGD("Leave " << __func__); delete[] innerBuffer; return;

case 1:

LOGFILE_DIAGNOSTIC_ERROR(); LOGD("Leave " << __func__); delete[] innerBuffer; return;

}

}

case 1:

switch (addIntoLogFile(echoError(), argc))

{

case 0:

LOGD("Leave " << __func__); delete[] innerBuffer; return;

case 1:

LOGFILE_DIAGNOSTIC_ERROR(); LOGD("Leave " << __func__); delete[] innerBuffer; return;

}

}

break;

case 1:

LOGFILE_DIAGNOSTIC_ERROR(); LOGD("Leave " << __func__); delete[] innerBuffer; return;

}

}

case 1:

switch (checkLog())

{

case 0:

switch (addIntoLogFile(paramError(argc)))

{

case 0:

LOGD("Leave " << __func__); delete[] innerBuffer; return;

case 1:

LOGFILE_DIAGNOSTIC_ERROR(); LOGD("Leave " << __func__); delete[] innerBuffer; return;

}

case 1:

switch (logFileCreate())

{

case 0:

switch (addIntoLogFile(paramError(argc)))

{

case 0:

LOGD("Leave " << __func__); delete[] innerBuffer; return;

case 1:

LOGFILE_DIAGNOSTIC_ERROR(); LOGD("Leave " << __func__); delete[] innerBuffer; return;

}

case 1:

LOGFILE_DIAGNOSTIC_ERROR(); LOGD("Leave " << __func__); delete[] innerBuffer;

//Successful package dispatch

//Successful add info

//DEBUG MESSAGE

//Failed to add info

//DEBUG MESSAGE

//Successful add info //DEBUG MESSAGE

//Failed to add info

//DEBUG MESSAGE

//Failed package dispatch

//Successful add info //DEBUG MESSAGE

//Failed to add info

//DEBUG MESSAGE

//DEBUG MESSAGE

//Incorrect parameter

//If log file exist

//Successful add info //DEBUG MESSAGE

//Failed to add info

//DEBUG MESSAGE

//If log file doesnt exist

//Successful file creation

//Successful add info //DEBUG MESSAGE

//Failed to add info

//DEBUG MESSAGE

//Failed to create log file

//DEBUG MESSAGE

return;

}

}

}

LOGD("Leave " << __func__); //DEBUG MESSAGE delete[] innerBuffer;

return;

}