procedure TForm1.SNAC_4_7(p:PPack);
var
i,cnt,T,MessageFormat,SubMode,SubMode2,Empty : word;
{myUIN,}
hisUIN : longint;
SubType : array[0..3] of byte;
MessageSubType : longint absolute SubType;
tmp,tmp2,tmp3 : PPack;
sTemp : string;
dTemp : TByteArray;
typemes,
{subtypemes,}
unk,modifier,lenmes : word;
// для SNAC(4,0B)-подтверждения принятых advanced сообщений
d1,d2 : longint;
ACK : TByteArray;
ind : word;
NewMsg : PMsgItem;
FG : array[0..3] of byte;
BG : array[0..3] of byte;
begin
// сохраняем Cookie-1 и Cookie-2
d1:=PacketRead32(p);
d2:=PacketRead32(p);
// читаем формат сообщения
MessageFormat := swap(PacketRead16(p));
// от кого ?
sTemp := PacketReadB_String(p);
// Cookie-1,Cookie-2 и некоторую другую часть пакета сохраним.
// Эти данные необходимо включить в ACK на это сообщение
ind:=0;
PLONG(@(ACK[ind]))^:=d1; inc(ind,4);
PLONG(@(ACK[ind]))^:=d2; inc(ind,4);
PWORD(@(ACK[ind]))^:=swap(MessageFormat);inc(ind,2);
PBYTE(@(ACK[ind]))^:=length(sTemp);inc(ind,1);
MOVE(sTemp[1],ACK[ind],length(sTemp));inc(ind,length(sTemp));
PWORD(@(ACK[ind]))^:=swap($0003);inc(ind,2);
// преобразуем его UIN из строки в longint
try hisUIN := strtoint(sTemp); except hisUIN:=0; end;
M(Memo,'< From: '+sTemp);
PacketRead16(p);
// узнаем сколько всего TLV во входящем пакете
cnt := swap(PacketRead16(p));
// читаем все эти TLV
for i:=1 to cnt do
// самый интересный - TLV(6)
if TLVReadStr(p,sTemp)=6 then begin
{ в TLV(6) - его статус }
end;
// анализируем каждый из форматов
case MessageFormat of
$0001: begin
M(Memo,'< Message-format:1 (SIMPLE)');
// чтение TLV(2) в sTemp
TLVReadStr(p,sTemp);
// скопируем sTemp во временный PPack,
// для удобства обработки
tmp := PacketNew;
PacketAppend(tmp,@(sTemp[1]),length(sTemp));
PacketGoto(tmp,0);
// обработаем его
PacketRead16(tmp);
PacketRead16(tmp);
PacketRead8(tmp);
PacketRead16(tmp);
// добрались до длины сообщения
lenmes := swap(PacketRead16(tmp))-4;
PacketRead32(tmp);
// читаем сообщение в sTemp
PacketRead(tmp,@sTemp[1],lenmes);
SetLength(sTemp,lenmes);
// анализ содержания сообщения
DoSimpleMsg(hisUIN,sTemp);
// удалим временный PPack
PacketDelete(tmp);
end;
$0002: begin
M(Memo,'< Message-format:2 (ADVANCED)');
// чтение TLV(5) в sTemp
TLVReadStr(p,sTemp);
// скопируем sTemp во временный PPack,
// для удобства обработки
tmp := PacketNew;
PacketAppend(tmp,@(sTemp[1]),length(sTemp));
PacketGoto(tmp,0);
// обработаем его
SubMode := swap(PacketRead16(tmp));
PacketRead32(tmp);
PacketRead32(tmp);
PacketRead(tmp,@dTemp,16);
case SubMode of
$0000: begin
M(Memo,'SubMode: $0000 NORMAL');
TLVReadWord(tmp,SubMode2);
// TLV(F) - пустой
TLVReadWord(tmp,Empty);
// прием и анализ TLV(2711)
T := TLVReadStr(tmp,sTemp);
if T=$2711 then begin
// сохраняем кусок данных для ACKа
MOVE(sTemp[1],ACK[ind],47);inc(ind,47);
PLONG(@(ACK[ind]))^:=0; inc(ind,4);
// используем временный PPack
tmp2 := PacketNew;
PacketAppend(tmp2,@(sTemp[1]),length(sTemp));
PacketGoto(tmp2,0);
PacketRead(tmp2,@dTemp,26);
PacketRead8(tmp2);
PacketRead16(tmp2);
PacketRead16(tmp2);
PacketRead16(tmp2);
PacketRead(tmp2,@dTemp,12);
// читаем ТИП сообщения
typemes := PacketRead8(tmp2);
{subtypemes := }PacketRead8(tmp2);
unk:=swap(PacketRead16(tmp2));
modifier:=swap(PacketRead16(tmp2));
M(Memo,'Unk: $'+inttohex(unk,4));
M(Memo,'Modifier: $'+inttohex(modifier,4));
// длина сообщения
lenmes := PacketRead16(tmp2);
// анализ сообщения
NewMsg:=DoMsg(true,typemes,
lenmes,PCharArray(@(tmp2^.data[tmp2^.cursor])),
hisUIN,Now2DateTime);
// небольшая перемотка
PacketGoto(tmp2,(tmp2^.cursor)+lenmes);
// читаем Foreground и Background Colors
PacketRead(tmp2,@FG,4);
PacketRead(tmp2,@BG,4);
if NewMsg<>nil then begin
NewMsg^.FG:='$00'+inttohex(FG[2],2)+
inttohex(FG[1],2)+
inttohex(FG[0],2);
NewMsg^.BG:='$00'+inttohex(BG[2],2)+
inttohex(BG[1],2)+
inttohex(BG[0],2);
end;
// удаление временного PPack
PacketDelete(tmp2);
// дозаполнение ACK
PWORD(@(ACK[ind]))^:= 1; inc(ind,2);
PBYTE(@(ACK[ind]))^:= 0; inc(ind,1);
PLONG(@(ACK[ind]))^:= 0; inc(ind,4);
PLONG(@(ACK[ind]))^:=-1; inc(ind,4);
// посылка ACKа
tmp3 := CreatePacket($2,SEQ);
SNACAppend(tmp3,$4,$0B);
PacketAppend(tmp3,@ACK[0],ind);
PacketSend(tmp3);
end;
// Submode:$0000
end;
$0001: M(Memo,'SubMode:$0001 ??? message canceled ???');
$0002: M(Memo,'SubMode:$0002 FILE-ACK');
// case SubMode
end;
PacketDelete(tmp);
end;
$0004: begin
M(Memo,'< Message-format:4 '+
'(url or contacts or auth-req or userAddedYou)');
TLVReadStr(p,sTemp);
tmp := PacketNew;
PacketAppend(tmp,@(sTemp[1]),length(sTemp));
PacketGoto(tmp,0);
hisUIN := PacketRead32(tmp);
typemes := PacketRead8(tmp);
{subtypemes := }
PacketRead8(tmp);
lenmes := PacketRead16(tmp);
DoMsg(true,typemes,
lenmes,PCharArray(@(tmp^.data[tmp^.cursor])),
hisUIN,Now2DateTime);
PacketDelete(tmp);
end;
else M(Memo,'< ??? SNAC 4,7; Message-format: '+s(MessageFormat));
// case MessageFormat
end;
end;
|