Надпись на могиле аськера: <Он добавил мир в игнор-лист>.
Для разбора конкретного примера возьмем ситуацию, когда мы запрашиваем у ICQ-сервера оффлайновые сообщения (т.е. те, которые накопились на сервере, пока нас не было в онлайне).
Запрос оффлайновых сообщений делаем с помощью SNAC(15,2), а ответ на него получим соответственно в SNAC(15,3). Оба этих SNACa имеют очень простой формат. Они содержат в себе только по одному TLV, а именно TLV(1). На первый взгляд все очень просто. Но... TLV(1), в свою очередь, имеет очень ветвистую структуру. (Такие особенности имеют и некоторые другие SNACи, например, SNAC(4,6) для передачи и SNAC(4,7) для приема сообщений).
В заметках к протоколу ICQv7 от Massimo Melina есть описание SNAC(15,2). Этот SNAC используется во множестве различных запросов. Я лишь выделю те строки, которые будут включены в наш запрос, а именно:
заголовок самого SNAC(15,2);
TLV(1), который включает в себя:
длину, следующих далее данных,
наш UIN,
тип запроса ($3С00),
cookie (по которому мы узнаем ответный SNAC(15,3) ).
В описании это находится вот здесь:
SNAC 15,02
TLV(1)
WORD (LE) bytes remaining, useless
UIN my uin
WORD type
WORD cookie
type = 3C00 // ask for offlines messages
nothing
type = 3E00 // ack to offline messages,
nothing type=D007
WORD subtype
subtype=9808 xml-stype in an LNTS
LNTS '' nameof required data ''
subtype=1F05 // simple query info
UIN user to request info subtype=B204 // query info about user
UIN user to request info subtype=D004 // query my info
UIN my uin
..............
..............
..............
В исходном коде это выглядит так:
// Get offline messages// создаем FLAP-заголовок с Channel_ID=2 и SEQ++
tmp := CreatePacket(2,SEQ);
// добавляем SNAC-заголовок SNAC(15,2)
SNACAppend(tmp,$15,$2);
// добавляем TLV(1) ($0001-Type, $000A-Length)
PacketAppend32(tmp,dswap($0001000A));
// добавляем саму Value Для TLV(1)
PacketAppend16(tmp, swap($0800));// бесполезная длина
PacketAppend32(tmp, UIN); // наш UIN
PacketAppend16(tmp, swap($3C00));// тип запроса
PacketAppend16(tmp, swap($0200));// cookie
PacketSend(tmp);
M(Memo,'> Get offline messages');
Этот кусок кода сгенерирует следующий дамп:
2A 02 36 86 00 18 00 15
00 02 00 00 00 87 00 02
00 01 00 0A 08 00 XX XX
XX XX 3C 00 02 00
Разпишем его в табличном виде для лучшего восприятия:
FLAP
Command Start
2A
Channel ID
02
Sequence Number
36 86
Data Field Length
00 18
SNAC (15,
02)
Family ID
00 15
SubType ID
00 02
Flags[0]
00
Flags[1]
00
Request ID
00 87 00
02
TLV
(1)
Type
00 01
Length
00 0A
Value
08 00
XX XX XX
XX
наш UIN
3C
00
запрос на
оффлайновые сообщения
02 00
cookie
Передадим пакет и от сервера получим FLAP-пакет с таким дампом:
2A 02 74 6D 00 4D 00 15
00 03 00 01 00 87 00 02
00 01 00 3F 3D 00 XX XX
XX XX 41 00 02 00 F8 5F
F1 08 D2 07 02 0C 10 12
01 00 25 00 EF F0 E8 E2
E5 F2 0D 0A FD F2 EE 20
F2 E5 F1 F2 EE E2 EE E5
20 F1 EE EE E1 F9 E5 ED
E8 E5 20 21 21 21 0D 0A
00 00 00
И снова распишем его в таблицу:
FLAP
Command Start
2A
Channel ID
02
Sequence Number
74 6D
Data Field Length
4D 00
SNAC (15,
03)
Family ID
00 15
SubType ID
00 03
Flags[0]
00
Flags[1]
01
Request ID
00 87 00 02
(такой же как и в запросе)
TLV
(1)
Type
00 01
Length
00 3F
Value
3D 00
XX XX XX XX
наш UIN
41
00
тип:
оффлайновое сообщение
02 00
cookie (как и в
запросе)
тело сообщения
XX XX XX
XX
его UIN
D2 07
год (2002)
02
месяц (февраль)
0C
день (12)
10
час
(16)
12
минуты (18)
01
под-тип
сообщения (обычное)
00
флаги сообщения
(?)
25
00
длина сообщения
(37)
EF F0 E8 E2 E5
F2 0D 0A FD F2 EE 20 F2 E5 F1 F2 EE E2 EE E5 20
F1 EE EE E1 F9 E5 ED E8 E5 20 21 21 21 0D 0A
00
текст
сообщения:
"привет это тестовое сообщение
!!!"
00 00
присутствют,
если сообщение единственное
В протокольных заметках я выделю ту часть описания SNAC(15,3), которая соответствует таблице:
SNAC 15,03
TLV(1)
WORD (LE) bytes remaining, useless
UIN my uin
WORD message-type
WORD cookie
message-type = 4100 // offline message
UIN his uin
WORD year (LE)
BYTE month (1=jan)
BYTE day
BYTE hour (GMT time)
BYTE minutes
BYTE msg-subtype
BYTE msg-flags
LNTS msg
WORD 0000, present only in single messages
message-type = 4200 // end of offline messages
BYTE unknown, usually 0
message-type = D007
2 BYTE unknown, usually 98 08
WORD length of the following NTS
NTS ""field-type""
field-type = DataFilesIP
6 BYTE unk, usually 2A 02 44 25 00 31
message-type = DA07
3 BYTE subtype
subtype=A4010A // wp-full-request result
wp-result-info
..............
..............
..............
subtype=B4000A // ack to remove user
empty
subtype=AA000A // ack to change password
empty
И "нарешти" - код для приема SNAC(15,3). Множественные комментарии, кажется тут уже излишни.
procedure TForm1.SNAC_15_3(p:PPack);
var MessageType,Cookie : word;
myUIN,hisUIN : longint;
year,month,day,hour,minute,typemes,subtypemes,lenmes : word;
tmp : PPack;
begin// просто пролетаем над началом TLV(1)
PacketRead32(p);
PacketRead16(p);
// а дальше имена переменных объясняют больше, чем комментарии
myUIN := PacketRead32(p);
MessageType := swap(PacketRead16(p));
Cookie := swap(PacketRead16(p));
M(Memo,'< Cookie: $'+inttohex(Cookie,4));
case MessageType of
$4100: begin// OFFLINE MESSAGE
hisUIN := PacketRead32(p);
M(Memo,'< Message-Type: $'+inttohex(MessageType,4));
M(Memo,'< OFFLINE MESSAGE from UIN: '+s(hisUIN));
year := PacketRead16(p);
month := PacketRead8(p);
day := PacketRead8(p);
hour := PacketRead8(p);
minute := PacketRead8(p);
typemes := PacketRead8(p);
subtypemes := PacketRead8(p);
lenmes := PacketRead16(p);
DoMsg(false,typemes,lenmes,PCharArray(@(p^.data[p^.cursor])),
hisUIN,UTC2LT(year,month,day,hour,minute));
end;
end;
end;
Тут можно на недельку передохнуть...
В скором времени я добавлю такие модули:
передача сообщений (SendMess);
прием сообщений (MessFrom);
информация о пользователе (UserInfo);
поиск пользователей по разным критериям (SearchUser);
...следите за обновлениями сайта
В статье "ICQ2000 сделай сам 7" автор Александр Вага описывает процесс создания запроса на получение оффлайновых сообщений в ICQ-сети с помощью SNAC(15,2) и приема ответа с помощью SNAC(15,3).
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.