teleport/client/tp_assist/ts_network.cpp

347 lines
9.7 KiB
C++

#include "stdafx.h"
#include "msocketx.h"
#include "ts_network.h"
#include <iostream>
using namespace std;
unsigned short CalcChecksum(char *pBuffer, int nLen)
{
//Checksum for ICMP is calculated in the same way as for
//IP header
//This code was taken from: http://www.netfor2.com/ipsum.htm
unsigned short nWord;
unsigned int nSum = 0;
int i;
//Make 16 bit words out of every two adjacent 8 bit words in the packet
//and add them up
for (i = 0; i < nLen; i = i + 2)
{
nWord = ((pBuffer[i] << 8) & 0xFF00) + (pBuffer[i + 1] & 0xFF);
nSum = nSum + (unsigned int)nWord;
}
//Take only 16 bits out of the 32 bit sum and add up the carries
while (nSum >> 16)
{
nSum = (nSum & 0xFFFF) + (nSum >> 16);
}
//One's complement the result
nSum = ~nSum;
return ((unsigned short)nSum);
}
bool ValidateChecksum(char *pBuffer, int nLen)
{
unsigned short nWord;
unsigned int nSum = 0;
int i;
//Make 16 bit words out of every two adjacent 8 bit words in the packet
//and add them up
for (i = 0; i < nLen; i = i + 2)
{
nWord = ((pBuffer[i] << 8) & 0xFF00) + (pBuffer[i + 1] & 0xFF);
nSum = nSum + (unsigned int)nWord;
}
//Take only 16 bits out of the 32 bit sum and add up the carries
while (nSum >> 16)
{
nSum = (nSum & 0xFFFF) + (nSum >> 16);
}
//To validate the checksum on the received message we don't complement the sum
//of one's complement
//One's complement the result
//nSum = ~nSum;
//The sum of one's complement should be 0xFFFF
return ((unsigned short)nSum == 0xFFFF);
}
int ICMPSendTo(ICMPheaderRet* pICMPheaderRet, char* pszRemoteIP, int nMessageSize, int nCount)
{
int nTimeOut = 500; //Request time out for echo request (in milliseconds)
ICMPheader sendHdr;
//char *pSendBuffer = NULL;
SOCKET sock;
sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); //Create a raw socket which will use ICMP
if (sock == INVALID_SOCKET)
{
return -1;
}
SOCKADDR_IN dest; //Dest address to send the ICMP request
memset(&dest, 0, sizeof(0));
dest.sin_addr.S_un.S_addr = inet_addr(pszRemoteIP);
dest.sin_family = AF_INET;
//dest.sin_port = rand (); //Pick a random port
int nResult = 0;
int nTry = 0;
int nSequence = 0;
fd_set fdRead;
//SYSTEMTIME timeSend, timeRecv;
unsigned long timeTick = 0;
int nTotalRoundTripTime = 0, nMaxRoundTripTime = 0, nMinRoundTripTime = -1, nRoundTripTime = 0;
int nPacketsSent = 0, nPacketsReceived = 0;
timeval timeInterval = { 0, 0 };
timeInterval.tv_usec = nTimeOut * 1000;
sendHdr.nId = htons(rand()); //Set the transaction Id
while (nPacketsSent < nCount)
{
//Create the message buffer, which is big enough to store the header and the message data
///pSendBuffer = new char [sizeof (ICMPheader) + nMessageSize];
char Sendbuf[1024] = { 0 };
int len = (sizeof(ICMPheader) + nMessageSize);
sendHdr.byCode = 0; //Zero for ICMP echo and reply messages
sendHdr.nSequence = htons(nSequence++);
sendHdr.byType = 8; //Eight for ICMP echo message
sendHdr.nChecksum = 0; //Checksum is calculated later on
memcpy_s(Sendbuf, sizeof(ICMPheader), &sendHdr, sizeof(ICMPheader)); //Copy the message header in the buffer
memset(Sendbuf + sizeof(ICMPheader), 'x', nMessageSize); //Fill the message with some arbitary value
//Calculate checksum over ICMP header and message data
sendHdr.nChecksum = htons(CalcChecksum(Sendbuf, sizeof(ICMPheader) + nMessageSize));
//Copy the message header back into the buffer
memcpy_s(Sendbuf, sizeof(ICMPheader), &sendHdr, sizeof(ICMPheader));
//::GetSystemTime (&timeSend);
timeTick = GetTickCount();
nResult = sendto(sock, Sendbuf, sizeof(ICMPheader) + nMessageSize, 0, (SOCKADDR *)&dest, sizeof(SOCKADDR_IN));
//Save the time at which the ICMP echo message was sent
++nPacketsSent;
if (nResult == SOCKET_ERROR)
{
cerr << endl << "An error occured in sendto operation: " << "WSAGetLastError () = " << WSAGetLastError() << endl;
//UnInitialize ();
closesocket(sock);
return -1;
}
next:
FD_ZERO(&fdRead);
FD_SET(sock, &fdRead);
if ((nResult = select(0, &fdRead, NULL, NULL, &timeInterval))
== SOCKET_ERROR)
{
cerr << endl << "An error occured in select operation: " << "WSAGetLastError () = " <<
WSAGetLastError() << endl;
closesocket(sock);
//delete []pSendBuffer;
return -2;
}
//printf("FD_ISSET Enter --- 0\n");
if (nResult > 0 && FD_ISSET(sock, &fdRead))
{
//printf("FD_ISSET Enter --- 1\n");
//Allocate a large buffer to store the response
char buf[1500] = { 0 };
struct sockaddr_in addr;
int addr_len = sizeof(struct sockaddr_in);
memset(&addr, 0, sizeof(sockaddr_in));
if ((nResult = recvfrom(sock, buf, 1500, 0, (struct sockaddr *)&addr, &addr_len))
== SOCKET_ERROR)
{
cerr << endl << "An error occured in recvfrom operation: " << "WSAGetLastError () = " <<
WSAGetLastError() << endl;
//UnInitialize ();
//delete []pSendBuffer;
closesocket(sock);
return -3;
}
//printf("FD_ISSET Enter --- 2 IP%s\n",inet_ntoa(addr.sin_addr));
string strIP = inet_ntoa(addr.sin_addr);
if (strIP.compare(pszRemoteIP) == 0)
{
//Get the time at which response is received
//::GetSystemTime (&timeRecv);
//We got a response so we construct the ICMP header and message out of it
ICMPheader recvHdr;
char *pICMPbuffer = NULL;
//The response includes the IP header as well, so we move 20 bytes ahead to read the ICMP header
pICMPbuffer = buf + sizeof(IPheader);
//ICMP message length is calculated by subtracting the IP header size from the
//total bytes received
int nICMPMsgLen = nResult - sizeof(IPheader);
//Construct the ICMP header
memcpy_s(&recvHdr, sizeof(recvHdr), pICMPbuffer, sizeof(recvHdr));
//Construct the IP header from the response
IPheader ipHdr;
memcpy_s(&ipHdr, sizeof(ipHdr), buf, sizeof(ipHdr));
recvHdr.nId = recvHdr.nId;
recvHdr.nSequence = recvHdr.nSequence;
recvHdr.nChecksum = ntohs(recvHdr.nChecksum);
if (recvHdr.byType == 0 &&
recvHdr.nId == sendHdr.nId &&
recvHdr.nSequence == sendHdr.nSequence &&
ValidateChecksum(pICMPbuffer, nICMPMsgLen) &&
memcmp(Sendbuf + sizeof(ICMPheader), buf + sizeof(ICMPheader) + sizeof(IPheader),
nResult - sizeof(ICMPheader) - sizeof(IPheader)) == 0)
{
printf("FD_ISSET Enter --- 3\n");
int nRoundTripTime = 0;
nRoundTripTime = (GetTickCount() - timeTick);
nTotalRoundTripTime = nTotalRoundTripTime + nRoundTripTime;
if (nMinRoundTripTime == -1)
{
nMinRoundTripTime = nRoundTripTime;
nMaxRoundTripTime = nRoundTripTime;
}
else if (nRoundTripTime < nMinRoundTripTime)
{
nMinRoundTripTime = nRoundTripTime;
}
else if (nRoundTripTime > nMaxRoundTripTime)
{
nMaxRoundTripTime = nRoundTripTime;
}
++nPacketsReceived;
}
else
{
cout << "The echo reply is not correct! Type : " << recvHdr.byType << endl;
}
}
else
{
goto next;
}
//Check if the response is an echo reply, transaction ID and sequence number are same
//as for the request, and that the checksum is correct
//if (recvHdr.byType == 0 &&
// recvHdr.nId == sendHdr.nId &&
// recvHdr.nSequence == sendHdr.nSequence &&
// ValidateChecksum (pICMPbuffer, nICMPMsgLen) &&
// memcmp (pSendBuffer + sizeof(ICMPheader), pRecvBuffer + sizeof (ICMPheader) + sizeof(IPheader),
// nResult - sizeof (ICMPheader) - sizeof(IPheader)) == 0)
//{
// printf("FD_ISSET Enter --- 3\n");
// int nRoundTripTime = 0;
// nRoundTripTime = (GetTickCount() - timeTick);
// nTotalRoundTripTime = nTotalRoundTripTime + nRoundTripTime;
// if (nMinRoundTripTime == -1)
// {
// nMinRoundTripTime = nRoundTripTime;
// nMaxRoundTripTime = nRoundTripTime;
// }
// else if (nRoundTripTime < nMinRoundTripTime)
// {
// nMinRoundTripTime = nRoundTripTime;
// }
// else if (nRoundTripTime > nMaxRoundTripTime)
// {
// nMaxRoundTripTime = nRoundTripTime;
// }
// ++nPacketsReceived;
//}
//else
//{
// cout << "The echo reply is not correct!" << endl;
//}
//delete []pRecvBuffer;
}
else
{
cout << "Request timed out. Tick : " << GetTickCount() << endl;
}
}
cout << endl << "Ping statistics for " << pszRemoteIP << ":" << endl << '\t' << "Packets: Sent = " << nPacketsSent << ", Received = " <<
nPacketsReceived << ", Lost = " << (nPacketsSent - nPacketsReceived) << " (" <<
((nPacketsSent - nPacketsReceived) / (float)nPacketsSent) * 100 << "% loss)" << endl << '\t';
pICMPheaderRet->nPacketsSent = nPacketsSent;
pICMPheaderRet->nPacketsReceived = nPacketsReceived;
if (nPacketsReceived > 0)
{
// cout << "\rApproximate round trip times in milli-seconds:" << endl << '\t' << "Minimum = " << nMinRoundTripTime <<
// "ms, Maximum = " << nMaxRoundTripTime << "ms, Average = " << nTotalRoundTripTime / (float)nPacketsReceived << "ms" << endl;
pICMPheaderRet->nMinRoundTripTime = nMinRoundTripTime;
pICMPheaderRet->nMaxRoundTripTime = nMaxRoundTripTime;
pICMPheaderRet->nAverageRoundTripTime = (int)(nTotalRoundTripTime / (float)nPacketsReceived);
}
else
{
pICMPheaderRet->nMinRoundTripTime = -1;
pICMPheaderRet->nMaxRoundTripTime = -1;
pICMPheaderRet->nAverageRoundTripTime = -1;
//getchar();
}
closesocket(sock);
//cout << '\r' << endl;
return 0;
}
bool TestTCPPort(const ex_astr& strServerIP, int port)
{
int icount = 0;
unsigned int uibegconn = GetTickCount();
unsigned int uicostconn = 0;
msocketx sock;
sock.create(SOCK_STREAM, IPPROTO_TCP);
sock.setsocktime(1000);
int iconn = sock.connect(strServerIP.c_str(), port, false);
bool bFailed = true;
while (++icount <= 2)
{
int nRet = sock.wait(1000, CAN_CONNECTX);
if (nRet < 0)
{
continue;
}
if ((nRet & CAN_CONNECTX) == CAN_CONNECTX)
{
return true;
}
else
{
continue;
}
}
return false;
}