Exemple #1
0
filetransfer*  CMsnProto::p2p_getSessionByCallID(const char* CallID, const char* wlid)
{
	if (CallID == NULL)
		return NULL;

	EnterCriticalSection(&sessionLock);

	filetransfer* ft = NULL;
	char* szEmail = NULL;
	for (int i=0; i < sessionList.getCount(); i++) 
	{
		filetransfer* FT = &sessionList[i];
		if (FT->p2p_callID && !_stricmp(FT->p2p_callID, CallID)) 
		{
 			if (_stricmp(FT->p2p_dest, wlid))
			{
				if (!szEmail)
					parseWLID(NEWSTR_ALLOCA(wlid), NULL, &szEmail, NULL);
				if (_stricmp(FT->p2p_dest, szEmail))
					continue;
			}
			ft = FT;
			break;
		}	
	}

	LeaveCriticalSection(&sessionLock);
	if (ft == NULL)
		MSN_DebugLog("Ignoring unknown session call id %s", CallID);

	return ft;
}
Exemple #2
0
ThreadData::~ThreadData()
{
	if ( s != NULL ) {
		MSN_DebugLog( "Closing connection handle %08X", s );
		Netlib_CloseHandle( s );
	}

	if ( mIncomingBoundPort != NULL ) {
		Netlib_CloseHandle( mIncomingBoundPort );
	}

	if ( mMsnFtp != NULL ) {
		delete mMsnFtp;
		mMsnFtp = NULL;
	}

	if ( hWaitEvent != INVALID_HANDLE_VALUE )
		CloseHandle( hWaitEvent );

	p2p_clearDormantSessions();

	free( mJoinedContacts );

	while (mFirstQueueItem != NULL)
	{
		TQueueItem* QI = mFirstQueueItem;
		mFirstQueueItem = mFirstQueueItem->next;
		free(QI);
}	}
Exemple #3
0
void CMsnProto::DecryptEchoPacket(UDPProbePkt& pkt)
{
	pkt.clientPort ^= 0x3141;
	pkt.discardPort ^= 0x3141;
	pkt.testPort ^= 0x3141;
	pkt.clientIP ^= 0x31413141;
	pkt.testIP ^= 0x31413141;


	IN_ADDR addr;
	MSN_DebugLog("Echo packet: version: 0x%x  service code: 0x%x  transaction ID: 0x%x",
		pkt.version, pkt.serviceCode, pkt.trId);
	addr.S_un.S_addr = pkt.clientIP;
	MSN_DebugLog("Echo packet: client port: %u  client addr: %s",
		pkt.clientPort, inet_ntoa(addr));
	addr.S_un.S_addr = pkt.testIP;
	MSN_DebugLog("Echo packet: discard port: %u  test port: %u test addr: %s",
		pkt.discardPort, pkt.testPort, inet_ntoa(addr));
}
Exemple #4
0
int __cdecl CMsnProto::SetStatus(int iNewStatus)
{
	if (m_iDesiredStatus == iNewStatus) return 0;

	m_iDesiredStatus = iNewStatus;
	MSN_DebugLog("PS_SETSTATUS(%d,0)", iNewStatus);

	if (m_iDesiredStatus == ID_STATUS_OFFLINE)
	{
		if (msnNsThread)
			msnNsThread->sendTerminate();
	}
	else if (!msnLoggedIn && m_iStatus == ID_STATUS_OFFLINE)
	{
		char szPassword[100];
		int ps = getStaticString(NULL, "Password", szPassword, sizeof(szPassword));
		if (ps != 0  || *szPassword == 0) 
		{
			SendBroadcast(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_WRONGPASSWORD);
			m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
			return 0;
		}	
		 
		if (*MyOptions.szEmail == 0) 
		{
			SendBroadcast(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_BADUSERID);
			m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
			return 0;
		}	

		sessionList.destroy();
		dcList.destroy();

		usingGateway = false;
		
		int oldMode = m_iStatus;
		m_iStatus = ID_STATUS_CONNECTING;
		SendBroadcast(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldMode, m_iStatus);

		ThreadData* newThread = new ThreadData;

		newThread->mType = SERVER_NOTIFICATION;
		newThread->mIsMainThread = true;

		newThread->startThread(&CMsnProto::MSNServerThread, this);
	}
	else 
		if (m_iStatus > ID_STATUS_OFFLINE) MSN_SetServerStatus(m_iDesiredStatus);

	return 0;
}
Exemple #5
0
void ThreadData::applyGatewayData( HANDLE hConn, bool isPoll )
{
	char szHttpPostUrl[300];
	getGatewayUrl( szHttpPostUrl, sizeof( szHttpPostUrl ), isPoll );

	MSN_DebugLog( "applying '%s' to %08X [%d]", szHttpPostUrl, this, GetCurrentThreadId() );

	NETLIBHTTPPROXYINFO nlhpi = {0};
	nlhpi.cbSize = sizeof(nlhpi);
	nlhpi.flags = NLHPIF_HTTP11;
	nlhpi.szHttpGetUrl = NULL;
	nlhpi.szHttpPostUrl = szHttpPostUrl;
	nlhpi.firstPostSequence = 1;
	MSN_CallService( MS_NETLIB_SETHTTPPROXYINFO, (WPARAM)hConn, (LPARAM)&nlhpi);
}
Exemple #6
0
void __cdecl msn_keepAliveThread( void* )
{
	msnPingTimeout = msnPingTimeoutCurrent;

	while( TRUE )
	{
		while ( --msnPingTimeout > 0 ) {
			if ( ::WaitForSingleObject( hKeepAliveThreadEvt, 1000 ) != WAIT_TIMEOUT ) {
				::CloseHandle( hKeepAliveThreadEvt ); hKeepAliveThreadEvt = NULL;
				MSN_DebugLog( "Closing keep-alive thread" );
				return;
		}	}

		msnPingTimeout = msnPingTimeoutCurrent = 45;

		/*
		 * if proxy is not used, every connection uses select() to send PNG
		 */

		if ( msnLoggedIn && !MyOptions.UseGateway )
			if ( MSN_GetByte( "KeepAlive", 0 ))
				msnNsThread->send( "PNG\r\n", 5 );
}	}
Exemple #7
0
filetransfer*  CMsnProto::p2p_getSessionByUniqueID(unsigned id)
{
	if (id == 0)
		return NULL;

	filetransfer* ft = NULL;
	EnterCriticalSection(&sessionLock);

	for (int i=0; i < sessionList.getCount(); i++) 
	{
		filetransfer* FT = &sessionList[i];
		if (FT->p2p_acksessid == id) 
		{
			ft = FT;
			break;
		}	
	}

	LeaveCriticalSection(&sessionLock);
	if (ft == NULL)
		MSN_DebugLog("Ignoring unknown unique id %08x", id);

	return ft;
}
Exemple #8
0
void CMsnProto::MSNatDetect(void)
{
	unsigned i;

	PHOSTENT host = gethostbyname("echo.edge.messenger.live.com");
	if (host == NULL)
	{
		MSN_DebugLog("P2PNAT could not find echo server \"echo.edge.messenger.live.com\"");
		return;
	}

	SOCKADDR_IN addr;
	addr.sin_family = AF_INET;
	addr.sin_port = _htons(7001);
	addr.sin_addr = *( PIN_ADDR )host->h_addr_list[0];

	MSN_DebugLog("P2PNAT Detected echo server IP %d.%d.%d.%d",
		addr.sin_addr.S_un.S_un_b.s_b1, addr.sin_addr.S_un.S_un_b.s_b2,
		addr.sin_addr.S_un.S_un_b.s_b3, addr.sin_addr.S_un.S_un_b.s_b4);

	SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

	connect(s, (SOCKADDR*)&addr, sizeof(addr));

	UDPProbePkt pkt = { 0 };
	UDPProbePkt pkt2;

	// Detect My IP
	pkt.version = 2;
	pkt.serviceCode = 4;
	send(s, (char*)&pkt, sizeof(pkt), 0);

	SOCKADDR_IN  myaddr;
	int szname = sizeof(myaddr);
	getsockname(s, (SOCKADDR*)&myaddr, &szname);

	MyConnection.intIP = myaddr.sin_addr.S_un.S_addr;
	MSN_DebugLog("P2PNAT Detected IP facing internet %d.%d.%d.%d",
		myaddr.sin_addr.S_un.S_un_b.s_b1, myaddr.sin_addr.S_un.S_un_b.s_b2,
		myaddr.sin_addr.S_un.S_un_b.s_b3, myaddr.sin_addr.S_un.S_un_b.s_b4);

	SOCKET s1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

	pkt.version = 2;
	pkt.serviceCode = 1;
	pkt.clientPort = 0x3141;
	pkt.clientIP = 0x31413141;

	UDPProbePkt rpkt = {0};

	// NAT detection
	for (i=0; i<4; ++i)
	{
		if (Miranda_Terminated()) break;

		// Send echo request to server 1
		MSN_DebugLog("P2PNAT Request 1 attempt %d sent", i);
		sendto(s1, (char*)&pkt, sizeof(pkt), 0, (SOCKADDR*)&addr, sizeof(addr));

		fd_set fd;
		FD_ZERO(&fd);
		FD_SET(s1, &fd);
		TIMEVAL tv = {0, 200000 * (1 << i) };

		if (select(1, &fd, NULL, NULL, &tv) == 1)
		{
			MSN_DebugLog("P2PNAT Request 1 attempt %d response", i);
			recv(s1, (char*)&rpkt, sizeof(rpkt), 0);
			pkt2 = rpkt;
			DecryptEchoPacket(rpkt);
			break;
		}
		else
			MSN_DebugLog("P2PNAT Request 1 attempt %d timeout", i);
	}

	closesocket(s);

	// Server did not respond
	if (i >= 4)
	{
		MyConnection.udpConType = conFirewall;
		closesocket(s1);
		return;
	}

	MyConnection.extIP = rpkt.clientIP;

	// Check if NAT not found
	if (MyConnection.extIP == MyConnection.intIP)
	{
		if (msnExternalIP != NULL && inet_addr(msnExternalIP) != MyConnection.extIP)
			MyConnection.udpConType = conISALike;
		else
			MyConnection.udpConType = conDirect;

		closesocket(s1);
		return;
	}

	// Detect UPnP NAT
	NETLIBBIND nlb = {0};
	nlb.cbSize = sizeof(nlb);
	nlb.pfnNewConnectionV2 = MSN_ConnectionProc;
	nlb.pExtra = this;

	HANDLE sb = (HANDLE) MSN_CallService(MS_NETLIB_BINDPORT, (WPARAM)hNetlibUser, (LPARAM)&nlb);
	if ( sb != NULL )
	{
		MyConnection.upnpNAT = htonl(nlb.dwExternalIP) == MyConnection.extIP;
		Sleep(100);
		Netlib_CloseHandle(sb);
	}

	DiscardExtraPackets(s1);

	// Start IP Restricted NAT detection
	UDPProbePkt rpkt2 = {0};
	pkt2.serviceCode = 3;
	SOCKADDR_IN addr2 = addr;
	addr2.sin_addr.S_un.S_addr = rpkt.testIP;
	addr2.sin_port = rpkt.discardPort;
	for (i=0; i<4; ++i)
	{
		if (Miranda_Terminated()) break;

		MSN_DebugLog("P2PNAT Request 2 attempt %d sent", i);
		// Remove IP restriction for server 2
		sendto(s1, NULL, 0, 0, (SOCKADDR*)&addr2, sizeof(addr2));
		// Send echo request to server 1 for server 2
		sendto(s1, (char*)&pkt2, sizeof(pkt2), 0, (SOCKADDR*)&addr, sizeof(addr));

		fd_set fd;
		FD_ZERO(&fd);
		FD_SET(s1, &fd);
		TIMEVAL tv = {0, 200000 * (1 << i) };

		if (select(1, &fd, NULL, NULL, &tv) == 1)
		{
			MSN_DebugLog("P2PNAT Request 2 attempt %d response", i);
			recv(s1, (char*)&rpkt2, sizeof(rpkt2), 0);
			DecryptEchoPacket(rpkt2);
			break;
		}
		else
			MSN_DebugLog("P2PNAT Request 2 attempt %d timeout", i);
	}

	// Response recieved so it's an IP Restricted NAT (Restricted Cone NAT)
	// (MSN does not detect Full Cone NAT and consider it as IP Restricted NAT)
	if (i < 4)
	{
		MyConnection.udpConType = conIPRestrictNAT;
		closesocket(s1);
		return;
	}

	DiscardExtraPackets(s1);

	// Symmetric NAT detection
	addr2.sin_port = rpkt.testPort;
	for (i=0; i<4; ++i)
	{
		if (Miranda_Terminated()) break;

		MSN_DebugLog("P2PNAT Request 3 attempt %d sent", i);
		// Send echo request to server 1
		sendto(s1, (char*)&pkt, sizeof(pkt), 0, (SOCKADDR*)&addr2, sizeof(addr2));

		fd_set fd;
		FD_ZERO(&fd);
		FD_SET(s1, &fd);
		TIMEVAL tv = {1 << i, 0 };

		if ( select(1, &fd, NULL, NULL, &tv) == 1 )
		{
			MSN_DebugLog("P2PNAT Request 3 attempt %d response", i);
			recv(s1, (char*)&rpkt2, sizeof(rpkt2), 0);
			DecryptEchoPacket(rpkt2);
			break;
		}
		else
			MSN_DebugLog("P2PNAT Request 3 attempt %d timeout", i);
	}
	if (i < 4)
	{
		// If ports different it's symmetric NAT
		MyConnection.udpConType = rpkt.clientPort == rpkt2.clientPort ?
			conPortRestrictNAT : conSymmetricNAT;
	}
	closesocket(s1);
}
Exemple #9
0
void CMsnProto::MSNConnDetectThread( void* )
{
	char parBuf[512] = "";

	memset(&MyConnection, 0, sizeof(MyConnection));

	MyConnection.icf = IsIcfEnabled();
	bool portsMapped = getByte("NLSpecifyIncomingPorts", 0) != 0;

	unsigned gethst = getByte("AutoGetHost", 1);
	switch (gethst)
	{
		case 0:
			MSN_DebugLog("P2PNAT User overwrote IP connection is guessed by user settings only");

			// User specified host by himself so check if it matches MSN information
			// if it does, move to connection type autodetection,
			// if it does not, guess connection type from available info
			getStaticString(NULL, "YourHost", parBuf, sizeof(parBuf));
			if (msnExternalIP == NULL || strcmp(msnExternalIP, parBuf) != 0)
			{
				MyConnection.extIP = inet_addr(parBuf);
				if (MyConnection.extIP == INADDR_NONE)
				{
					PHOSTENT myhost = gethostbyname(parBuf);
					if (myhost != NULL)
						MyConnection.extIP = ((PIN_ADDR)myhost->h_addr)->S_un.S_addr;
					else
						setByte("AutoGetHost", 1);
				}
				if (MyConnection.extIP != INADDR_NONE)
				{
					MyConnection.intIP = MyConnection.extIP;
					MyConnection.udpConType = MyConnection.extIP ? (ConEnum)portsMapped : conUnknown;
					MyConnection.CalculateWeight();
					return;
				}
				else
					MyConnection.extIP = 0;
			}
			break;

		case 1:
			if (msnExternalIP != NULL)
				MyConnection.extIP = inet_addr(msnExternalIP);
			else
			{
				gethostname(parBuf, sizeof(parBuf));
				PHOSTENT myhost = gethostbyname(parBuf);
				if (myhost != NULL)
					MyConnection.extIP = ((PIN_ADDR)myhost->h_addr)->S_un.S_addr;
			}
			MyConnection.intIP = MyConnection.extIP;
			break;

		case 2:
			MyConnection.udpConType = conUnknown;
			MyConnection.CalculateWeight();
			return;
	}

	if (getByte( "NLSpecifyOutgoingPorts", 0))
	{
		// User specified outgoing ports so the connection must be firewalled
		// do not autodetect and guess connection type from available info
		MyConnection.intIP = MyConnection.extIP;
		MyConnection.udpConType = (ConEnum)portsMapped;
		MyConnection.upnpNAT = false;
		MyConnection.CalculateWeight();
		return;
	}

	MSNatDetect();

	// If user mapped incoming ports consider direct connection
	if (portsMapped)
	{
		MSN_DebugLog("P2PNAT User manually mapped ports for incoming connection");
		switch(MyConnection.udpConType)
		{
		case conUnknown:
		case conFirewall:
		case conISALike:
			MyConnection.udpConType = conDirect;
			break;

		case conUnknownNAT:
		case conPortRestrictNAT:
		case conIPRestrictNAT:
		case conSymmetricNAT:
			MyConnection.upnpNAT = true;
			break;
		}
	}

	MSN_DebugLog("P2PNAT Connection %s found UPnP: %d ICF: %d", conStr[MyConnection.udpConType],
		MyConnection.upnpNAT, MyConnection.icf);

	MyConnection.CalculateWeight();
}
Exemple #10
0
void __cdecl MSNServerThread( ThreadData* info )
{
	if ( !sttRedirectorWasChecked ) {
		sttRedirectorWasChecked = true;
		MSN_StartThread(( pThreadFunc )msn_RedirectorThread, NULL );
	}

	NETLIBOPENCONNECTION tConn = { 0 };
	tConn.cbSize = sizeof( tConn );
	tConn.flags = NLOCF_V2;

 	char* tPortDelim = strrchr( info->mServer, ':' );
	if ( tPortDelim != NULL )
		*tPortDelim = '\0';

	if ( MyOptions.UseGateway && !MyOptions.UseProxy ) {
		tConn.szHost = MSN_DEFAULT_GATEWAY;
		tConn.wPort = 80;
	}
	else {
		tConn.szHost = info->mServer;
		tConn.wPort = MSN_DEFAULT_PORT;

		if ( tPortDelim != NULL ) {
			int tPortNumber;
			if ( sscanf( tPortDelim+1, "%d", &tPortNumber ) == 1 )
				tConn.wPort = ( WORD )tPortNumber;
	}	}

	MSN_DebugLog( "Thread started: server='%s', type=%d", tConn.szHost, info->mType );

	info->s = ( HANDLE )MSN_CallService( MS_NETLIB_OPENCONNECTION, ( WPARAM )hNetlibUser, ( LPARAM )&tConn );
	if ( info->s == NULL ) {
		MSN_DebugLog( "Connection Failed (%d)", WSAGetLastError() );

		switch ( info->mType ) {
		case SERVER_NOTIFICATION:
		case SERVER_DISPATCH:
			MSN_SendBroadcast( NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_NOSERVER );
			MSN_GoOffline();
			break;
		}

		return;
	}

	if ( MyOptions.UseGateway )
		MSN_CallService( MS_NETLIB_SETPOLLINGTIMEOUT, WPARAM( info->s ), 2 );

	MSN_DebugLog( "Connected with handle=%08X", info->s );

	if ( info->mType == SERVER_DISPATCH || info->mType == SERVER_NOTIFICATION ) {
		if ( MyOptions.UseMSNP11 )
			info->sendPacket( "VER", "MSNP11 MSNP10 CVR0" );
		else
			info->sendPacket( "VER", "MSNP10 MSNP9 CVR0" );
	}
	else if ( info->mType == SERVER_SWITCHBOARD ) {
		char tEmail[ MSN_MAX_EMAIL_LEN ];
		MSN_GetStaticString( "e-mail", NULL, tEmail, sizeof( tEmail ));
		info->sendPacket( info->mCaller ? "USR" : "ANS", "%s %s", tEmail, info->mCookie );
	}
	else if ( info->mType == SERVER_FILETRANS && info->mCaller == 0 ) {
		info->send( "VER MSNFTP\r\n", 12 );
	}

	if ( info->mIsMainThread ) {
		MSN_EnableMenuItems( TRUE );

		msnPingTimeout = msnPingTimeoutCurrent;

		msnNsThread = info;
		if (hKeepAliveThreadEvt == NULL) {
			hKeepAliveThreadEvt = ::CreateEvent( NULL, TRUE, FALSE, NULL );
			MSN_StartThread(( pThreadFunc )msn_keepAliveThread, NULL );
	}	}

	MSN_DebugLog( "Entering main recv loop" );
	info->mBytesInData = 0;
	while ( TRUE ) {
		int handlerResult;

		int recvResult = info->recv( info->mData + info->mBytesInData, sizeof( info->mData ) - info->mBytesInData );
		if ( recvResult == SOCKET_ERROR ) {
			MSN_DebugLog( "Connection %08p [%d] was abortively closed", info->s, GetCurrentThreadId());
			break;
		}

		if ( !recvResult ) {
			MSN_DebugLog( "Connection %08p [%d] was gracefully closed", info->s, GetCurrentThreadId());
			break;
		}

		info->mBytesInData += recvResult;

		if ( info->mCaller == 1 && info->mType == SERVER_FILETRANS ) {
			handlerResult = MSN_HandleMSNFTP( info, info->mData );
			if ( handlerResult )
				break;
		}
		else {
			while( TRUE ) {
				char* peol = strchr(info->mData,'\r');
				if ( peol == NULL )
					break;

				if ( info->mBytesInData < peol-info->mData+2 )
					break;  //wait for full line end

				char msg[ sizeof(info->mData) ];
				memcpy( msg, info->mData, peol-info->mData ); msg[ peol-info->mData ] = 0;

				if ( *++peol != '\n' )
					MSN_DebugLog( "Dodgy line ending to command: ignoring" );
				else
					peol++;

				info->mBytesInData -= peol - info->mData;
				memmove( info->mData, peol, info->mBytesInData );
				MSN_DebugLog( "RECV:%s", msg );

				if ( !isalnum( msg[0] ) || !isalnum(msg[1]) || !isalnum(msg[2]) || (msg[3] && msg[3]!=' ')) {
					MSN_DebugLog( "Invalid command name" );
					continue;
				}

				if ( info->mType != SERVER_FILETRANS ) {
					if ( isdigit(msg[0]) && isdigit(msg[1]) && isdigit(msg[2]))   //all error messages
						handlerResult = MSN_HandleErrors( info, msg );
					else
						handlerResult = MSN_HandleCommands( info, msg );
				}
				else handlerResult = MSN_HandleMSNFTP( info, msg );

				if ( handlerResult )
					goto LBL_Exit;
		}	}

		if ( info->mBytesInData == sizeof( info->mData )) {
			MSN_DebugLog( "sizeof(data) is too small: the longest line won't fit" );
			break;
	}	}

LBL_Exit:
	if ( info->mIsMainThread ) {
		MSN_GoOffline();
		msnNsThread = NULL;
		if ( hKeepAliveThreadEvt )
			SetEvent( hKeepAliveThreadEvt );
	}

	MSN_DebugLog( "Thread [%d] ending now", GetCurrentThreadId() );
}