⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 client.cpp

📁 stun的一个客户端例子
💻 CPP
📖 第 1 页 / 共 4 页
字号:

	AddrLocal.sin_family = AF_INET;
	AddrLocal.sin_addr.s_addr = INADDR_ANY;
	AddrLocal.sin_port = 0;

	//Bind 1 valid port and try to detect NAT characteristics.
    for(i = 0; i < 4; i++)
	{
        log_on_error(sEcho = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP), "Creating echo socket", LAB_DONE);
        log_on_error(setsockopt(sEcho,SOL_SOCKET,SO_REUSEADDR,(char *)&nOne,sizeof(nOne)), "Setting SO_REUSEADDR", LAB_DONE);

LAB_TRY_BIND:
        if (AddrLocal.sin_port == 0) 
		{
            AddrLocal.sin_port = htons(uwTryBindPort);
            uwTryBindPort++;
        }
        log_on_error(bind(sEcho,(struct sockaddr *)&AddrLocal, nAddrLocalLen), "Binding to local address", LAB_BIND_ERR);
        goto LAB_SOCK_READY;

LAB_BIND_ERR:
        AddrLocal.sin_port = 0;
        goto LAB_TRY_BIND;

LAB_SOCK_READY:
        uwPortLocal[i] = ntohs(AddrLocal.sin_port);
		XCheckConeTCPProbe(sServerLog, sEcho, i, &unAddrGlobal[i], &uwPortGlobal[i]);
#ifdef _WIN32
		Sleep(50);
#else
		XSleep(0, 50);
#endif
    }

    XAnalyzeNature(unAddrGlobal, uwPortGlobal, uwPortLocal, 4, PRO_TCP);
    nErr = ERR_NONE;

LAB_DONE:
    return nErr;
}

/***********************************************************************
 * FUNCTION:		XCheckConeTCPProbe() 
 * DESCRIPTION:  	This function try to connect to the echo service with different IP-PORT combinations and 
 *					then get the public IP and port of the client. 
 * PARAMETERS:		-> sServerLog: The STUNT server socket. This must be a valid socket connecting
 *									with STUNT server.
 *					-> sEcho: A echo socket created in XCheckConeTCP(). It will be used to connect to the 
 *								echo service of STUNT server.
 *					-> nSeq: Test sequence number (0 ~ 4).
 *					<-> *punResAddr: The public address of the client returned from the STUNT server.
 *					<-> *puwResPort: The public port of the client returned from the STUNT server.
 * RETURNED:		N/A
 * REVISION HISTORY:
 ***********************************************************************/
void XCheckConeTCPProbe(SOCKET sServerLog, SOCKET sEcho, INT32 nSeq, UINT32 *punResAddr, UINT16 *puwResPort) 
{
    struct sockaddr_in AddrEcho;
    struct sockaddr_in AddrLocal;
#ifdef _WIN32
	INT32 nAddrLocalLen = sizeof(AddrLocal);
#else
	socklen_t nAddrLocalLen = sizeof(AddrLocal);
#endif
    char chBuf[256];
    Echo Rep;
	//Using in macro by Saikat: 
	SOCKET sock_logr = sServerLog;
	/////////////////////////////////////////////////////////////

	//try 4 combinations of the echo service - IP1:Port1, IP1:Port2, IP2:Port1, IP2:Port2
    AddrEcho.sin_family = AF_INET;
    AddrEcho.sin_addr.s_addr = nSeq / 2 == 0 ? g_ServerInfo.nIP1 : g_ServerInfo.nIP2;
    AddrEcho.sin_port = nSeq % 2 == 0 ? g_ServerInfo.wPort1 : g_ServerInfo.wPort2;

    log_on_error(getsockname(sEcho,(struct sockaddr *)&AddrLocal, &nAddrLocalLen), "Resolving local address", LAB_DONE);
#ifdef _WIN32
	_snprintf(chBuf, 256, "Sending TCP probe %d: %d.%d.%d.%d:%d => %d.%d.%d.%d:%d",
				nSeq + 1,
				IPPORT(AddrLocal.sin_addr.s_addr, AddrLocal.sin_port),
				IPPORT(AddrEcho.sin_addr.s_addr, AddrEcho.sin_port)
			 );
#else
	snprintf(chBuf, 256, "Sending TCP probe %d: %d.%d.%d.%d:%d => %d.%d.%d.%d:%d",
				nSeq + 1,
				IPPORT(AddrLocal.sin_addr.s_addr, AddrLocal.sin_port),
				IPPORT(AddrEcho.sin_addr.s_addr, AddrEcho.sin_port)
			);
#endif
	log_on_error(connect(sEcho, (struct sockaddr *)&AddrEcho, sizeof(AddrEcho)), chBuf, LAB_DONE);
    log_on_read_error(sEcho, &Rep, sizeof(Rep), "Reading server response", LAB_DONE);
#ifdef _WIN32
	_snprintf(chBuf, 256, "PROBE TCP %d: %d.%d.%d.%d:%d (%d.%d.%d.%d:%d) => %d.%d.%d.%d:%d",
				nSeq,
				IPPORT(AddrLocal.sin_addr.s_addr, AddrLocal.sin_port),
				IPPORT(Rep.nIP, Rep.wPort),
				IPPORT(AddrEcho.sin_addr.s_addr, AddrEcho.sin_port)
			 );
#else    
	snprintf(chBuf, 256, "PROBE TCP %d: %d.%d.%d.%d:%d (%d.%d.%d.%d:%d) => %d.%d.%d.%d:%d",
				nSeq,
				IPPORT(AddrLocal.sin_addr.s_addr, AddrLocal.sin_port),
				IPPORT(Rep.nIP, Rep.wPort),
				IPPORT(AddrEcho.sin_addr.s_addr, AddrEcho.sin_port)
			);
#endif
	//Log the procedure on STUNT server
	log1(sServerLog, "%s", chBuf);

	//Return the result
	*punResAddr = Rep.nIP;
	*puwResPort = ntohs(Rep.wPort);

LAB_DONE:
    close2(sEcho);
    return;
}

/***********************************************************************
 * FUNCTION:		XAnalyzeNature() 
 * DESCRIPTION:  	This function analyzes the passed in IP:Port data and write the result on fingerprint  
 * PARAMETERS:		
 *					->	*punAddrGlobal	The pointer which points to a global (public) IP array.
 *					->	*puwPortGlobal	The pointer which points to a global (public) Port array
 *					->	*puwPortLocal	The pointer which points to a local (private) Port array
 *					<->	nTimes	Test times. The value is also the size of the above arrays
 *					<->	nProtocol	Always PRO_TCP in this library.
 * RETURNED:		N/A
 * REVISION HISTORY:
 ***********************************************************************/
void XAnalyzeNature(UINT32 *punAddrGlobal, UINT16 *puwPortGlobal, UINT16 *puwPortLocal, INT32 nTimes, E_Protocol nProtocol) 
{
    INT32	nTmp = 0, 
			nTmp2[2][4], 
			i = 0, 
			nDelta = 0;

    for (i = 0; i < nTimes; i++) 
	{
		//?? seems impossible to be equal zero
		if (g_Fingerprint.nGAddr == 0) 
			g_Fingerprint.nGAddr = punAddrGlobal[i];
		// an abnormal result
		if (punAddrGlobal[i] != g_Fingerprint.nGAddr) 
		{
			g_Fingerprint.nGAddr = 0xFFFFFFFF;
            break;
        }
    }

	//Port Preserving : If Ports on local and NAT are the same in different connections
	nTmp = 0;
    for (i = 0; i < nTimes; i++) 
	{
        if (puwPortLocal[i] == puwPortGlobal[i]) 
			nTmp++;
    }
    if (nTmp > 1) 
	{
        switch(nProtocol) 
		{
        case PRO_TCP:
			g_Fingerprint.TCP.bPortPreserving = 1;
            break;
        }
    }

	//NAT type: Cone or Symmetric is determined by the global port status.
    for (i = 0; i < 4; i++) 
	{
        INT32 j = 0;
        for(j = 0; j < 2; j++) 
		{
            nTmp2[j][i] = 0;
        }
    }

    for (i = 1; i < nTimes; i++) 
	{
        INT32 j = 0;
        nTmp = puwPortGlobal[i] - puwPortGlobal[i-1];
        if (nTmp < 0) 
			nTmp += 65536;
        for(j = 0; j < 4; j++) 
		{
            if (nTmp2[0][j] == nTmp) 
			{
                nTmp2[1][j]++;
                break;
            }
        }
        if (j == 4) 
		{
            for(j = 0; j < 4; j++) 
			{
                if (nTmp2[1][j] == 0) 
				{
                    nTmp2[1][j]++;
                    nTmp2[0][j] = nTmp;
                    break;
                }
            }
        }
    }

    nTmp = 0;
    nDelta = 0xFFFFFFFF;
    for(i = 0; i < 4; i++) 
	{
        if (nTmp2[1][i] >= nTmp) 
		{
            nTmp = nTmp2[1][i];
            nDelta = nTmp2[0][i];
        }
    }

    switch(nProtocol) 
	{
    case PRO_TCP:
        g_Fingerprint.TCP.nIncrement = (nTmp == 1) ? RANDOM_INCREMENT : nDelta;
        break;
    }

}

/***********************************************************************
 * FUNCTION:		XGenFingerprint() 
 * DESCRIPTION:  	This function interprets the binary fingerprint data to a readable string.  
 * PARAMETERS:		
 *					<->	*pchPrint	A buffer for storing the readable fingerprint string.
 *					->	nSize	Size of the above string
 * RETURNED:		N/A
 * REVISION HISTORY:
 ***********************************************************************/
void XGenFingerprint(CHAR *pchPrint, INT32 nSize) 
{
    strncpy(pchPrint, "", nSize);
    strncat(pchPrint, "TCP ", nSize);
	strncat(pchPrint, g_Fingerprint.TCP.bPortPreserving?"PORT-PRESERVING ":"NON-PORT-PRESERVING ", nSize);

	if (g_Fingerprint.TCP.nIncrement == 0) 
        strncat(pchPrint, "CONE ",nSize);
	else if (g_Fingerprint.TCP.nIncrement == RANDOM_INCREMENT) 
        strncat(pchPrint, "RANDOM-SYMMETRIC ",nSize);
    else
#ifdef _WIN32
		_snprintf(pchPrint+strlen(pchPrint), nSize-strlen(pchPrint), "DELTA-%d-SYMMETRIC ", g_Fingerprint.TCP.nIncrement);
#else
		snprintf(pchPrint+strlen(pchPrint), nSize-strlen(pchPrint), "DELTA-%d-SYMMETRIC ", g_Fingerprint.TCP.nIncrement);
#endif

}

/***********************************************************************
 * FUNCTION:		XWriteFingerprint() 
 * DESCRIPTION:  	This function writes the NAT fingerprint to specified file on the local machine.  
 * PARAMETERS:		-> sServerLog: The STUNT server socket. This must be a valid socket connecting
 *									with STUNT server.
 * RETURNED:		ERR_NONE: successful
 *					ERR_FAIL: failed
 * REVISION HISTORY:
 ***********************************************************************/
INT32 XWriteFingerprint(SOCKET sServerLog) 
{
    INT32 nFD = 0;
    unlink(FINGERPRINT_FILE);

	//Using in macro by Saikat: 
	SOCKET sock_logr = sServerLog;
	/////////////////////////////////////////////////////////////

#ifdef _WIN32    
	log_on_error(nFD = _open(FINGERPRINT_FILE, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE), "Opening fingerprint file", LAB_DONE);
#else
	log_on_error(nFD = open(FINGERPRINT_FILE, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR), "Opening fingerprint file", LAB_DONE);
#endif
	log_on_error(write(nFD, &g_Fingerprint, sizeof(g_Fingerprint)) == sizeof(g_Fingerprint) ? 0 : -1, "Dumpting fingerprint to file", LAB_ERR);

LAB_DONE:
    close(nFD);
    return ERR_NONE;
LAB_ERR:
    close(nFD);
    return ERR_FAIL;
}

/***********************************************************************
 * FUNCTION:		XReadFingerprint() 
 * DESCRIPTION:  	This function read fingerprint file and write the data on the global 
 *					fingerprint variable.  
 * PARAMETERS:		N/A
 * RETURNED:		ERR_NONE: successful
 *					ERR_FAIL: failed
 * REVISION HISTORY:
 ***********************************************************************/
INT32 XReadFingerprint(void) 
{
    INT32 nFD = 0;
	INT32 nErr = ERR_NONE;

	g_Fingerprint.chID[0] = '\0';

#ifdef _WIN32
    nFD = _open(FINGERPRINT_FILE, O_RDONLY | O_BINARY);
#else
    nFD = open(FINGERPRINT_FILE, O_RDONLY, S_IRUSR | S_IWUSR);
#endif
	if (nFD == -1) 
		nErr = ERR_FAIL;

    if (read(nFD, &g_Fingerprint, sizeof(g_Fingerprint)) != sizeof(g_Fingerprint)) 
		nErr = ERR_FAIL;

	//check build version
	if (g_Fingerprint.nClientVer != BUILD_VER) 
		nErr = ERR_FAIL;

	//check client ID
	if (g_Fingerprint.chID[0] == '\0') 
		nErr = ERR_FAIL;

	close(nFD);

	if (nErr == ERR_FAIL)
	{
		unlink(FINGERPRINT_FILE);
		strcpy(g_chClientID, g_Fingerprint.chID);
		memset(&g_Fingerprint, 0, sizeof(g_Fingerprint));
	}

	return nErr;
}

/////////////////////////////////////////////////////////////////////////
//Utilities
/////////////////////////////////////////////////////////////////////////
/***********************************************************************
 * FUNCTION:		XInitSockAddr() 
 * DESCRIPTION:  	Initialize socket address.
 * PARAMETERS:		<-> *SockAddr:	The socket address object needed to set.
 *					-> wfamily:	Net family
 *					-> pchAddr: Socket address in string. Pass NULL if pass in converted data
 *					-> uwPort: Socket port
 *					-> unConvertedAddr: converted address
 *					-> uwConvertedPort: converted port
 * RETURNED:			always ERR_NONE
 * REVISION HISTORY:
 ***********************************************************************/
INT32 XInitSockAddr(struct sockaddr_in *pSockAddr, INT16 wFamily, const CHAR * pchAddr, UINT16 uwPort, UINT32 unConvertedAddr, UINT16 uwConvertedPort)
{
	if (pchAddr != NULL)
	{
		pSockAddr->sin_family = wFamily;
		pSockAddr->sin_addr.s_addr = inet_addr(pchAddr);
		pSockAddr->sin_port = htons(uwPort);
	}
	else
	{
		pSockAddr->sin_family = wFamily;
		pSockAddr->sin_addr.s_addr = unConvertedAddr;
		pSockAddr->sin_port = uwConvertedPort;
	}
	return ERR_NONE;
}

/***********************************************************************
 * FUNCTION:		XSleep() 
 * DESCRIPTION:  	A delay function.
 * PARAMETERS:		-> nSec:	Time value, in seconds.
 *					-> nUsec:	Time value, in microseconds
 * RETURNED:		N/A
 * REVISION HISTORY:
 ***********************************************************************/
void XSleep(INT32 nSec, INT32 nUSec)
{
	struct timeval tv;
	fd_set s;
	
	FD_ZERO(&s);
	tv.tv_sec = nSec;
	tv.tv_usec = nUSec;

	select(0, NULL, NULL, NULL, &tv);
}

/***********************************************************************
 * FUNCTION:		XGetErrno() 
 * DESCRIPTION:  	Get errno in windows and lunux.
 * PARAMETERS:		N/A
 * RETURNED:		WIN_32: window socket error code
 *					o/w:	errno					
 * REVISION HISTORY:
 ***********************************************************************/
INT32 XGetErrno(void)
{
#ifdef _WIN32
	return (WSAGetLastError());
#else
	return errno;
#endif
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -