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

📄 xtunnelsservermain.cpp

📁 xtunnel nat/fw traversal source code
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*	File:       XTunnelsServerMain.cp	Contains:   The X-Tunnels server for Xten's SIP clients to communicate across firewalls with.	Copyright:  (c) 2003 by Xten Networks, Inc., all rights reserved.*///#if DEBUG#include <iostream>//#endif // DEBUG#include <map>#include <deque>#include <stdio.h>#include <unistd.h>#include <errno.h>#include <sys/wait.h>#include <netinet/in.h>#include <sys/socket.h>#include <arpa/inet.h>#include <signal.h>#include "uici.h"#include "uiciudp.h"#include "uiciname.h"#include "restart.h"#include "XTunnelsProtocol.h"#include "XTunnelsFamilyData.h"#include "XTunnelsChildData.h"#include "XTunnelsParentData.h"#include "XTunnelsXCipher.h"#include "uuid.h"#include "md5.h"//#if DEBUGusing std::cout;using std::endl;//#endif // DEBUGusing std::map;using std::max;using std::min;using std::deque;using std::pair;using std::make_pair;using namespace XTunnels;#define IGNORE_UNIMPLEMENTED 0// set to 0 to allow anonymous clients to login with an arbitrary host name #define ENFORCE_ANONYMOUS_HOST_LIMITS 1#if VS_TARGET_OS_MAC#pragma mark *** anonymous local implementations#endif // VS_TARGET_OS_MACnamespace {#if VS_TARGET_OS_MAC#pragma mark *** server globals#endif // VS_TARGET_OS_MACSChild *g_pChildren = NULL; // [kMaximumClients]; // = { 0 };// one way child to server pipes -- we don't expect contention problems hereint g_pStatusInfoPipe[2] = { 0 };#if VS_TARGET_OS_MAC#pragma mark *** child globals#endif // VS_TARGET_OS_MACunsigned long sBoundUDPRedirectAddress = 0;u_port_t sBoundUDPRedirectPort = 0;bool sForwardPacketsToUDPRedirectPort = false;// for login/authenticationbool sReopenSession = false;uuid_t sRequestedSession;// = { 0 };int g_iHostMax = 0; // retrieved from database with password, stored until we find out if connection is newmap<long,long> g_cUDPPorts; // added to at client's requestunsigned long g_ulActiveSinglePorts = 0;unsigned long g_ulActiveDualPorts = 0;// for tracking real time bandwidth usagetypedef pair<struct timeval, unsigned long> TPacketStamp;deque<TPacketStamp> g_cInPackets;deque<TPacketStamp> g_cOutPackets;// execution controlbool sQuitting = false;// for disconnect packetconst char* sMessageUnexpectedError = "Unexpected communication error"; // kDisconnectReasonMustCloseconst char* sMessageDataTooLarge = "Sent data exceeded server size limit"; // kDisconnectReasonMustCloseconst char* sMessageFailedDecryption = "Sent data could not be decrypted"; // kDisconnectReasonMustCloseconst char* sMessageIllegalDestination = "Destination address is blocked"; // kDisconnectReasonMustCloseconst char* g_pMessageFailedEncryption = "Internal data encryption error"; // kDisconnectReasonMustCloseconst char* g_pMessageBadMagicNumber = "Data integrity check failed"; // kDisconnectReasonMustCloseconst char* g_pMessageServerQuitting = "Server is shutting down"; // kDisconnectReasonMustCloseconst char* sMessageTooBusy = "Too many clients connected"; // kDisconnectReasonTooBusyconst char* sMessagePoliteGoodbye = "Client sent disconnect packet"; // kDisconnectReasonNormalconst char* sMessageTimedOut = "Server timed out waiting for input"; // kDisconnectReasonTimeoutconst char* g_szMessageIPRejected = "Client IP address is in a denied address range"; // kDisconnectReasonAuthenticationFailedconst char* g_szMessageBadAddress = "Client IP address is not in an acceptable address range"; // kDisconnectReasonAuthenticationFailedconst char* g_szMessageNoAnonymousLogin = "Client may not login anonymously"; // kDisconnectReasonAuthenticationFailedconst char* g_szMessageAuthenticationFailed = "Client authentication failed"; // kDisconnectReasonAuthenticationFailedconst char* sMessageMustAuthenticate = "Non-anonymous logins must authenticate"; // kDisconnectReasonAuthenticationFailedconst char* g_szMessageBadUser = "Unknown user or wrong password"; // kDisconnectReasonAuthenticationFailedconst char* g_szMessageBadAnonymousHost = "Anonymous users not allowed for this host"; // kDisconnectReasonAuthenticationFailedconst char* sMessageBadVersion = "Client is incompatible version"; // kDisconnectReasonWrongVersionconst char* sMessageBadEncryption = "Server does not understand encryption algorithm used"; // kDisconnectReasonWrongVersionconst char* sMessageBadLogin = "Server does not understand login method used"; // kDisconnectReasonWrongVersion#if VS_TARGET_OS_MAC#pragma mark *** helpers#endif // VS_TARGET_OS_MACvoid CleanChildPipes(SChild &tChild)   {	if (tChild.m_pChild2ServerPipe[0])		r_close(tChild.m_pChild2ServerPipe[0]);	if (tChild.m_pChild2ServerPipe[1])		r_close(tChild.m_pChild2ServerPipe[1]);	tChild.m_pChild2ServerPipe[0] = 0;	tChild.m_pChild2ServerPipe[1] = 0;	if (tChild.m_pServer2ChildPipe[0])		r_close(tChild.m_pServer2ChildPipe[0]);	if (tChild.m_pServer2ChildPipe[1])		r_close(tChild.m_pServer2ChildPipe[1]);	tChild.m_pServer2ChildPipe[0] = 0;	tChild.m_pServer2ChildPipe[1] = 0;	/* 	if (g_pChildren[i].pipefd[0])		r_close(g_pChildren[i].pipefd[0]);	if (g_pChildren[i].pipefd[1])		r_close(g_pChildren[i].pipefd[1]);	g_pChildren[i].pipefd[0] = 0;	g_pChildren[i].pipefd[1] = 0;	*/   }int CountActiveChildren()	{	int total = 0;	for (unsigned long i = 0; i < g_ulMaximumClients; i++)		if (g_pChildren[i].status > SChild::eAvailable)			total++;	return total;	}int CountHostConnections(const char* szHost)	{#if DEBUG	cout << "X-Tunnels: CountHostConnections for  host " << szHost << endl;#endif //DEBUG	int total = 0;	for (unsigned long i = 0; i < g_ulMaximumClients; i++)		if (g_pChildren[i].status > SChild::eAvailable)		   {#if DEBUG	      cout << "Active child index " << i << " has host " << g_pChildren[i].m_szHost << endl;#endif //DEBUG		   if (0 == strcmp(g_pChildren[i].m_szHost, szHost))   			total++;   		}#if DEBUG	cout << "X-Tunnels: CountHostConnections for host " << szHost << " returning total active of " << total << endl;#endif //DEBUG	return total;	}int NextAvailableChildIndex()	{	// look for one that's empty	for (unsigned long i = 0; i < g_ulMaximumClients; i++)		if (g_pChildren[i].status == SChild::eAvailable)			return i;				// look for something on deathwatch to kill early	for (unsigned long i = 0; i < g_ulMaximumClients; i++)		if (g_pChildren[i].status == SChild::eDeathwatch)			{			kill(g_pChildren[i].pid, SIGTERM);			// that should cause a signal to clear its status/pid before we allocate new one, we trust			return i;			}		// nope, don't accept this one, hit design limit	return -1;	}void CleanPackets(deque<TPacketStamp>& ioQueue)	{	struct timeval tNow;	gettimeofday(&tNow, NULL);	int32_t iLastSecond = tNow.tv_sec - 1;	long count = ioQueue.size();	for (int i = 0; i < count; i++)		{		if (ioQueue[0].first.tv_sec == tNow.tv_sec)		   {	      // defintely nothing a second old left	      return;		   }		else if (ioQueue[0].first.tv_sec == iLastSecond)		   {	      // need to check microseconds   		if (ioQueue[0].first.tv_usec < tNow.tv_usec)   			ioQueue.pop_front();   		else   			return;		   }		else		   {	      // must be at least 10002 microseconds old, discard immediately   		ioQueue.pop_front();		   }		}	}unsigned long CountBytes(deque<TPacketStamp>& ioQueue)	{	unsigned long total = 0;	long count = ioQueue.size();	for (int i = 0; i < count; i++)		total += ioQueue[0].second;	return total;	}void LogIncomingPacket(unsigned long inPacketSize)	{	g_tCurrentChildInfo.incomingbytes += inPacketSize;		CleanPackets(g_cInPackets);	struct timeval tNow = { 0 };	gettimeofday(&tNow, NULL);	g_cInPackets.push_back(make_pair(tNow, inPacketSize));	}void LogOutgoingPacket(unsigned long inPacketSize)	{	g_tCurrentChildInfo.outgoingbytes += inPacketSize;		CleanPackets(g_cOutPackets);	struct timeval tNow = { 0 };	gettimeofday(&tNow, NULL);	g_cOutPackets.push_back(make_pair(tNow, inPacketSize));	}unsigned long GetIncomingBandwidth()	{	CleanPackets(g_cInPackets);	return CountBytes(g_cInPackets);	}unsigned long GetOutgoingBandwidth()	{	CleanPackets(g_cOutPackets);	return CountBytes(g_cOutPackets);	}void SendGoodbyePacket(int clientfd, long inReason, const char* inMessage, bool bSetAlarm)	{	if (!clientfd)		return;		// no need to timeout if we're saying goodbye	// but we don't want to set alarm if we're the parent!!	if (bSetAlarm)      ChildData()->SetAlarm(ESentPacket);			int messagelen = strlen(inMessage);	if (messagelen > (int)EMaxSmallBufferSize)		messagelen = EMaxSmallBufferSize;	TGoodbyePacket tGoodbye;	tGoodbye.m_tHeader.commandid = HOST2XT32(EMessageDisconnect);	tGoodbye.reason = HOST2XT32(inReason);	tGoodbye.messagesize = HOST2XT16(messagelen);	strncpy(tGoodbye.message, inMessage, messagelen);		long lPacketSize = sizeof(unsigned long) + sizeof(unsigned short) + messagelen;		int iTempSocket = sClientTCPSocket;	sClientTCPSocket = clientfd;   ChildData()->SendPacketToClient(reinterpret_cast<TXTunnelsPacket*>(&tGoodbye), lPacketSize, false);	sClientTCPSocket = iTempSocket;	}int CheckForDeathwatch()   {   int iResult = 0;   	// don't worry about errors closing client sockets	if (sClientTCPSocket)		{		if (sQuitReason)         SendGoodbyePacket(sClientTCPSocket, sQuitReason, sQuitMessage, true);		r_close(sClientTCPSocket);		sClientTCPSocket = 0;		}	if (sClientUDPRedirectSocket)		{		r_close(sClientUDPRedirectSocket);		sClientUDPRedirectSocket = 0;		}	// for our accounting, to be stored in database at quit time	SaveClientSessionTraffic(g_tCurrentChildInfo, true);/*#if DEBUG   {   time_t tNow = time(NULL);   int iReceiveTimeout = g_tLastReceivedFromClient + EChildDisconnectTimeOut - tNow;   int iSendTimeout = g_tLastSentToClient + EChildPingClientTimeOut - tNow;   cout << "X-Tunnels: child " << getpid() << " CheckForDeathwatch() called with receive timeout " << iReceiveTimeout <<          " seconds, send timeout " << iSendTimeout << " seconds " << endl;	}#endif //DEBUG*/   bool bDeathwatchable = true;   if (ChildData()->IsAnonymous())      bDeathwatchable = false;   if (g_tCurrentChildInfo.status < SChild::eActive)      bDeathwatchable = false;   if (bDeathwatchable)      {      TChildToParentPipePacket tPipedInfo = { 0 };      tPipedInfo.m_ulPacketType = EInfoPacketChildOnDeathwatch;      tPipedInfo.m_tDeathwatch.m_ulStatus = SChild::eDeathwatch;      tPipedInfo.m_tDeathwatch.m_ulChildIndex = sCurrentChildIndex;      int iPortCount = tPipedInfo.m_tDeathwatch.m_ulActivePortCount = g_cUDPPorts.size();   	if (tPipedInfo.m_tDeathwatch.m_ulActivePortCount > EMaxActivePortCount)   		{   		tPipedInfo.m_tDeathwatch.m_ulActivePortCount = EMaxActivePortCount;   #if DEBUG   		cout << "X-Tunnels: child " << getpid() << " CheckForDeathwatch found portcount was over " << EMaxActivePortCount << ", that seems pretty unlikely" << endl;   #endif //DEBUG   		}   	int iCurrentPortIndex = 0;   	for (map<long,long>::const_iterator iter = g_cUDPPorts.begin(); iter != g_cUDPPorts.end(); ++iter)   		{   		long port = iter->first;   		tPipedInfo.m_tDeathwatch.m_pActivePorts[iCurrentPortIndex] = port;   		iCurrentPortIndex++;   		// don't assume list stays static   		iPortCount--;   		if (!iPortCount)   			break;   		}   	// write whole thing for simplicity -- assume that it'll be less than PIPE_BUF so written atomically    	long iPipeResult = PipeWrite(g_pChild2ParentInfoPipe, &tPipedInfo, sizeof(tPipedInfo));   	if (sizeof(tPipedInfo) != iPipeResult)   		{   #if DEBUG   		cout << "X-Tunnels: child " << getpid() << " CheckForDeathwatch failed to pipe deathwatch status to parent, exiting immediately!" << endl;   #endif //DEBUG   		exit(1);   		}        	if (-1 == kill(getppid(), SIGUSR2))   		{   #if DEBUG   		cout << "X-Tunnels: child " << getpid() << " CheckForDeathwatch failed to signal deathwatch status availability to parent" << endl;

⌨️ 快捷键说明

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