Exemple #1
0
void netbios_name::Receiver(UCHAR lsn)
{
	// Created by Ilja Razinkov (also known as IPv6), 2002, [email protected]
	// Keep this comment if you redistribute this file

	UCHAR* SMBBlock = (UCHAR*)mir_alloc( 65536 );
	if ( ! SMBBlock )
		return;

	CStringA sTo, sFrom, sMessage;
	UCHAR nRes;
	for (;;)
	{
		ZeroMemory( SMBBlock, 65536 );

		// Получение очередного блока данных
		WORD iReadedBytes = 65535;
		nRes = pluginNetBIOS.Recv (m_lana, lsn, SMBBlock, iReadedBytes);
		if (nRes != NRC_GOODRET)
		{
			LOG( "Receiver : Error while receiving data block" );
			break;
		}

		// Смотрим что к нам пришло - сообщение или что-то неизвестное
		if ( iReadedBytes < 4 || *(DWORD*)SMBBlock != SMB_MAGIC )
		{
			LOG( "Receiver : Unsupported data 0x%08x", *(DWORD*)SMBBlock );
			break;
		}

		UCHAR iMsgType = SMBBlock [4];
		if (iMsgType != SMBsends &&
			iMsgType != SMBsendstrt &&
			iMsgType != SMBsendend &&
			iMsgType != SMBsendtxt)
		{
			LOG( "Receiver : Unsupported message type 0x%02x", iMsgType );
			break;
		}

		// Шлём подтверждение
		UCHAR szReply [SMB_HEADER_SIZE + 5];
		UCHAR* szReplyData =
			pluginNetBIOS.SetSMBHeaderCommand (szReply, iMsgType, sizeof (szReply));
		if (iMsgType == SMBsendstrt)
		{
			// Код сообщения
			static UCHAR rnd = 1;
			szReplyData [0] = 1;		// Номер сообщения
			szReplyData [1] = rnd++;	//
			if ( rnd > 5 )
				rnd = 1;
		}
		nRes = pluginNetBIOS.Send (m_lana, lsn, szReply,
			(WORD)( (iMsgType == SMBsendstrt) ? (SMB_HEADER_SIZE + 5) : (SMB_HEADER_SIZE + 3) ) );
		if ( nRes != NRC_GOODRET )
		{
			// Нефатальная ошибка
			LOG( "Receiver : Error while sending ack" );
		}

		// Действия в зависимости от типа сообщения
		if (iMsgType == SMBsends)
		{
			LOG( "Receiver : Got single-block message" );
			// Короткое сообщение, вытаскиваем данные и выходим...
			sFrom = (const char*) SMBBlock + SMB_HEADER_SIZE + 4;
			int iFromOffset = sFrom.GetLength ();
			sTo = (const char*) SMBBlock + SMB_HEADER_SIZE + 4 + iFromOffset + 2;
			int iToOffset = sTo.GetLength ();
			sMessage = (const char*) SMBBlock + SMB_HEADER_SIZE + 4 + iFromOffset + 2 +
				iToOffset + 4;
			break;
		}
		else if (iMsgType == SMBsendstrt)
		{
			LOG( "Receiver : Got start of multi-block message" );
			// Кусочковое сообщение, начало, смотрим от кого и кому
			sFrom = (const char*) SMBBlock + SMB_HEADER_SIZE + 4;
			int iFromOffset = sFrom.GetLength ();
			sTo = (const char*) SMBBlock + SMB_HEADER_SIZE + iFromOffset + 4 + 2;
		}
		else if (iMsgType == SMBsendtxt)
		{
			// Кусочковое сообщение, блок с данными, конкатенируем...
			int iConcatSize = iReadedBytes - SMB_HEADER_SIZE - 8;
			LOG( "Receiver : Got text (%d-%d bytes) of multi-block message", sMessage.GetLength(), sMessage.GetLength() + iConcatSize - 1 );
			sMessage.Append ((const char*) (SMBBlock + SMB_HEADER_SIZE + 8), iConcatSize);
		}
		else if (iMsgType == SMBsendend)
		{
			LOG( "Receiver : Got end of multi-block message" );
			// Кусочковое сообщение, конец, все получено, выходим
			break;
		}
	}

	sMessage.Replace( "\x14", "\r\n" ); // <14> -> <CR><LF>

	sTo.OemToAnsi();
	sFrom.OemToAnsi();
	sMessage.OemToAnsi();

	// Смотрим информацию о сессии
	CStringA sRealFrom;
	if (GetRealSender (lsn, sRealFrom))
	{
		LOG( "Receiver : Message from \"%s\" (real \"%s\") to \"%s\"", (LPCSTR)sFrom, (LPCSTR)sRealFrom, (LPCSTR)sTo);
		sFrom = sRealFrom;
	}
	else
	{
		LOG( "Receiver : Message from \"%s\" (real sender unknown) to \"%s\"", (LPCSTR)sFrom, (LPCSTR)sTo);
	}

	// Скажем до свиданья...
	pluginNetBIOS.Hangup (m_lana, lsn);

	// Открываем сообщение (пустое игнорируем)
	if ( ! sMessage.IsEmpty() )
	{
		ReceiveContactMessage( CA2T( sFrom ), CA2T( sTo ), CA2T( sMessage ), sMessage.GetLength ());
	}
	else
	{
		LOG( "Receiver : Ignoring empty message" );
	}

	mir_free( SMBBlock );
}
DWORD WINAPI NBMsgReciever(LPVOID lpdwstatus)
{
	NBMsgRecData* pMsgData=(NBMsgRecData*)lpdwstatus;
	if(!pMsgData){
		return 0;
	}
	int iRes=TRUE, nRes=0;
	UINT m_lsn=pMsgData->lsn;
	CNCB m_thisNCB(pMsgData->pParent->m_iLana);
	CString sReceivedMessage="";
	char szMessageData[RECBUFFER_SIZE]="";
	int iBlocksCount=0,iMesDataOffset=0;
	CString sTo, sFrom, sMessage;
	BYTE iMsgType=0;
	try{
		while(TRUE){
			char SMBBlock[255]="";
			memset(SMBBlock,0,sizeof(SMBBlock));
			nRes = m_thisNCB.Receive(m_lsn,(char *)SMBBlock,sizeof(SMBBlock));
			if ( nRes != NRC_GOODRET){
				objLog.AddMsgLogLine(DEFAULT_GENERALLOG,"Error while receiving netbios data block, err. #%i",nRes);
				// Возвращаемся чтобы показать хотябы часть
				//throw FALSE;
				break;
			}
			iBlocksCount++;
			UINT iReadedBytes=(UINT)m_thisNCB.GetLength();
			// Смотрим что к нам пришло - сообщение или запрос о статусе или что-то неизвестное
			if(CheckSpecialMessages(pMsgData->pParent, SMBBlock, m_lsn, m_thisNCB, iMsgType)){
				throw TRUE;
			}
			// Шлем подтверждение (3/5 ноля после SMB HEADER)
			char szReply[SMB_HEADER_SIZE+5]="";
			char* szReplyData=SetSMBHeaderCommand(szReply,iMsgType,sizeof(szReply));
			if(iMsgType==0xd5){
				// Код сообщения - случайные два байта
				szReplyData[0]=rnd(1,5);
				szReplyData[1]=rnd(1,5);
			}
			m_thisNCB.Send(m_lsn,szReply,(iMsgType==0xd5)?SMB_HEADER_SIZE+5:SMB_HEADER_SIZE+3);
			// Действия в зависимости от типа сообщения
			if(iMsgType==0xd0){// Короткое сообщение, вытаскиваем данные и выходим...
				sFrom=(const char*)SMBBlock+SMB_HEADER_SIZE+4;
				int iFromOffset=strlen(sFrom);
				sTo=(const char*)SMBBlock+SMB_HEADER_SIZE+4+iFromOffset+2;
				int iToOffset=strlen(sTo);
				sMessage=(const char*)SMBBlock+SMB_HEADER_SIZE+4+iFromOffset+2+iToOffset+4;
				break;
			}
			if(iMsgType==0xd5){// Кусочковое сообщение, начало, Смотрим от кого и кому
				sFrom=(const char*)SMBBlock+SMB_HEADER_SIZE+4;
				int iFromOffset=strlen(sFrom);
				sTo=(const char*)SMBBlock+SMB_HEADER_SIZE+iFromOffset+4+2;
			}
			if(iMsgType==0xd7){// Кусочковое сообщение, блок с данными, Конкатенируем...
				int iConcatSize=iReadedBytes-SMB_HEADER_SIZE-8;
				if(iMesDataOffset+iConcatSize+3>RECBUFFER_SIZE){
					// Буффер готов к переполнению, сбрасываем в выходную строку...
					szMessageData[iMesDataOffset]=0;
					sMessage+=szMessageData;
					iMesDataOffset=0;
				}
				memcpy(szMessageData+iMesDataOffset,SMBBlock+SMB_HEADER_SIZE+8,iConcatSize);
				iMesDataOffset+=iConcatSize;
			}
			if(iMsgType==0xd6){// Кусочковое сообщение, конец, Все получено, выходим
				break;
			}
		}
		// К этому моменту сообщение полностью получено
		if(iMsgType!=0xd0){
			// Для кусочкового сообщения доберем данные из буфера
			szMessageData[iMesDataOffset]=0;
			sMessage+=szMessageData;
			iMesDataOffset=0;
		}
		// Открываем сообщение
		sFrom.OemToAnsi();
		sFrom+="/nb";
		sMessage.Replace("\r\n","\n");
		sMessage.Replace("\x14","\n");// Специально для TrayPopup
		sMessage.OemToAnsi();
		// Смотрим информацию о сессии
		CString sRealFrom;
		GetRealSender(pMsgData->pParent, m_lsn, m_thisNCB, sRealFrom);
		OpenMessage(sFrom,sTo,sMessage,sRealFrom);
	}catch(int e){
		iRes=e;
	}
	m_thisNCB.Hangup(m_lsn);
	delete pMsgData;
	return iRes;
}