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; }