С.Кадаков
Глава 1 Процедура авторизации.
Мы начинаем обсуждать команды протокола. В нашем, самом первом,
приложении нам их понадобится совсем немного. Начнем с процедуры авторизации,
выполняемой одной из команд семейства BIND.
Команды BIND.
Как уже говорилось, это семейство включает три команды:
- bind_receiver -- сообщает SMSC, что ESME подключается для приема
сообщений. Такой режим (только прием) характерен, например, для пэйджинговых
шлюзов.
- bind_transmitter -- сообщает SMSC, что ESME подключается для передачи
сообщений. Данный режим используется, в частности, при организации рассылок (в
том числе, к сожалению, и спама).
- bind_transceiver -- сообщает SMSC, что ESME подключается для приема и
передачи (т. е. в полнодуплексной моде). Этот режим удобен для создания
полнофункциональных шлюзов.
Ниже мы рассмотрим каждую из команд в отдельности и приведем
формат пакетов. Как уже отмечалось, все команды (пакеты) SMPP должны
предваряться заголовком. В заголовке команды поле command_id должно содержать
соответствующее значение.
bind_receiver. command_id = 0x01
Тело пакета bind_receiver состоит из следующих полей:
Field name |
Size (octets) |
Type |
Description |
system_id |
Var. max 16 |
C-Octet String |
Идентифицирует ESME. Можно рассматривать это поле, как
"username". |
password |
Var. max 9 |
C-Octet String |
Пароль для аутентификации. |
system_type |
Var. max 13 |
C-Octet String |
Необязательное. Используется для указания категории ESME, например
"WWW", "E-MAIL" и т. д. Если не используется, должно
содержать один октет NULL (0x0) |
interface_version |
1 |
Integer |
Идентифицирует версию протокола SMPP, поддерживаемую ESME.
0x00-0x33 указывают, что поддерживается версия 3.3 или более ранняя. 0x34
указывает, что поддерживается версия 3.4 |
addr_ton |
1 |
Integer |
Указывает тип адреса (TON - Type Of Number) ESME. (см. ниже). Если
неизвестен, выставляется в NULL |
addr_npi |
1 |
Integer |
Указывает индикатор плана номеров (NPI -- Numbering Plan
Indicator). (см. ниже). Если неизвестен, выставляется в NULL |
address_range |
Var. max 41 |
C-Octet String |
Адрес или диапазон адресов, обслуживаемых ESME. Если неизвестен,
выставляется в NULL |
bind_receiver_resp. command_id = 0x80000001
Тело пакета bind_receiver_resp состоит из следующих
полей (*):
Field name |
Size (octets) |
Type |
Description |
system_id |
Var. max 16 |
C-Octet String |
Подтвержденный идентификатор ESME. |
sc_interface_version |
- |
TLV |
Необязательное поле в формате TLV. Информирует о версии протокола
SMPP, поддерживаемой SMSC |
(*) -- В том случае, если поле command_status заголовка содержит ненулевое
значение (т. е. информирует об ошибке) тело пакета не передается.
bind_transmitter. command_id = 0x02
Формат и назначение полей тела пакета bind_transmitter
совпадает с форматом и назначением полей тела пакета bind_receiver.
bind_transmitter_resp. command_id = 0x80000002
Формат и назначение полей тела пакета
bind_transmitter_resp совпадает с форматом и назначением полей тела
пакета bind_receiver_resp.
bind_tranceiver. command_id = 0x03
Формат и назначение полей тела пакета bind_transceiver
совпадает с форматом и назначением полей тела пакета bind_receiver.
bind_tranceiver_resp. command_id = 0x80000003
Формат и назначение полей тела пакета
bind_transceiver_resp совпадает с форматом и назначением полей тела
пакета bind_receiver_resp.
Параметры TON и NPI.
Параметры TON и NPI не являются специфичными для протокола
SMPP, поэтому мы здесь не будем останавливаться на них подробно, а просто
приведем их возможные значения (подробнее об этих параметрах можно прочитать в
документации GSM):
TON |
Value (bin) |
Unknown |
00000000 |
International |
00000001 |
National |
00000010 |
Network Specific |
00000011 |
Subscriber Number |
00000100 |
Alphanumeric |
00000101 |
Abbreviated |
00000110 |
Reserved |
All others |
NPI |
Value (bin) |
Unknown |
00000000 |
ISDN (E163/E164) |
00000001 |
Data (X.121) |
00000011 |
Telex (F.69) |
00000100 |
Land Mobile (E.212) |
00000110 |
National |
00001000 |
Private |
00001001 |
ERMES |
00001010 |
Internet (IP) |
00001100 |
WAP Client Id (to be defined by WAP Forum) |
00010010 |
Reserved |
All others |
Generic Negative Result (generic_nack)
Как уже отмечалось, любая из команд, испущенная той или иной из
сторон должна квитироваться ACK'ом (за единственным, упомянутым в прошлой статье
исключением). При этом поле command_id заголовка ACK'а должно содержать
соответствующее значение (равное command_id оригинальной команды с выставленным
31-м битом), а поле sequence_number заголовка должно указывать номер транзакции
оригинальной команды. Однако в некоторых случаях, в частности, когда принимающая
сторона не может распознать заголовок оригинальной команды -- например, при
возникновении "мусора" в TCP/IP канале -- информация, необходимая для
формирования корректного ACK'а может оказаться недоступной. В таких случаях
принимающая сторона отвечает специальным пакетом, называемым generic_nack
(command_id = 0x80000000). Данный пакет состоит из одного заголовка с указанным
command_id. Поле command_status содержит соответствующий код ошибки, а поле
sequence_number может содержать NULL (0x0), если не удалось распознать номер
транзакции оригинальной команды.
Замечания.
Несколько слов по поводу направления передачи данных по
соединениям, т. к. могут возникать недоразумения, связанные с названиями сессий.
Например, если ESME авторизовалось с помощью команды bind_transmitter и
сессия перешла в состояние BOUND_TX, не следует думать, что SMSC не
может передавать данные в такое соединение (т. е., что программист избавлен
от вызова recv(2) с этим сокетом). Напротив, еще раз подчеркнем, что
ACK'и передаются в рамках того же соединения (т. е. в тот же сокет), что
и оригинальные команды. С другой стороны, разумеется, входящие сообщения (т. е.
от SMSC к ESME) не могут быть переданы по соединению, находящемуся в
BOUND_TX. Это важный момент и вот почему: как мы договорились, мы будем
работать в т. н. Store And Forward Mode, при этом сообщения сначала
помещаются в базу данных SMSC, а потом предпринимаются попытки их доведения.
Таким образом, факт помещения в базу данных (подтверждаемый ACK'ом) еще не
означает, что конечный пользователь получил данное сообщение, кроме того,
оно вообще может быть не доведено до истечения срока годности в том случае,
например, если аппарат пользователя остается отключенным не протяжении
нескольких дней. SMSC сигнализирует о переходе сообщения в финальное состояние
(доставлено/не может быть доставлено) с помощью (специального вида) команды
deliver_sm, т. е. той же команды с помощью которой передаются
входящие сообщения, и которая ... не может быть передана в
соединение находящееся в BOUND_TX! В действительности, такие сообщения,
называемые delivery receipts некоторое время хранятся на SMSC и
передаются в первое же, авторизовавшееся с помощью bind_receiver,
соединение с тем же system_id. Таким образом, достаточно время от времени
открывать сессию с помощью bind_receiver и "снимать" delivery
receipt'ы и входящие сообщения, буде таковые найдутся, или просто сразу же
открывать две сессии. Понятно, что для сессий в состоянии BOUND_TRX таких
проблем не существует. Однако, в случаях больших загрузок предпочтительней иметь
отдельные сессии на прием и передачу (возможно, в разных потоках исполнения --
threads) чтобы распараллелить эти операции.
Глава 2. Промежуточный итог 2
В данной главе мы обсудили процедуру авторизации поверх
сокетного соединения. Как мы видим, она не слишком сложна, хотя здесь есть
некоторые интересные моменты. Нам осталось обсудить команды передачи и приема
сообщений и мы вплотную приблизимся к кодированию. Оставайтесь с нами!
Языки программирования: разное
|