Процедура авторизации.
Мы начинаем обсуждать команды протокола. В нашем, самом первом, приложении нам их понадобится совсем немного. Начнем с процедуры авторизации, выполняемой одной из команд семейства 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
В данной главе мы обсудили процедуру авторизации поверх сокетного соединения. Как мы видим, она не слишком сложна, хотя здесь есть некоторые интересные моменты. Нам осталось обсудить команды передачи и приема сообщений и мы вплотную приблизимся к кодированию.
No comments:
Post a Comment