В статье дается краткое описание IRC (Internet relay chat) протокола и его особенностей. Описываются возможные программные решения для реализации собственного IRC сервера.
Ключевые слова: IRC, network, архитектура, internet relay chat, разработка.
IRC сеть
IRC (англ. Internet relay chat) — протокол прикладного уровня, работающий по модели Клиент/Сервер, для обмена в основном текстовыми сообщениями между пользователями (клиентами).
Был разработан в 1988 году. В виду простоты технической реализации был очень популярным средством общения в 90-е 00-е годы — более миллиона пользователей по всему миру [6]. В настоящее время популярен в качестве средства отправки/приема сообщения ботами в ботнетах (например в сети интернет-вещей).
Интересно, что международная спецификация протокола появилась не одновременно с первоначальной версией, а лишь в 1993 году (RFC 1459 [1]). В 2000 году она была дополнена RFC 2810, 2811, 2812, 2813 [2–5]. Данные спецификации не определяют строгий стандарт реализации протокола, а дают лишь общее (хоть и подробное) описание структуры и общих принципов работы IRC сети.
Архитектура IRC сети
Структурная схема IRC сети представлена на рисунке 1.
Рис. 1. Структурная схема IRC сети
Серверы — это основа IRC сети. Они обеспечивают точку, к которой клиенты могут подключаться, чтобы общаться друг с другом, и точку для подключения других серверов. Таким образом формируется IRC сеть. Единственная сетевая конфигурация, разрешенная для серверов IRC — это конфигурация связующего дерева (spanning-tree), где каждый сервер действует как центральный узел для остальной части сети, которую он видит. Важно заметить, что при такой конфигурации в сети запрещены петли из соединений серверов [1; 2].
Клиент — это все, что подключается к серверу, но не другой сервер. Каждый клиент отличается от других клиентов уникальным никнеймом. Длина никнейма четко задается в RFC 1459 (9 символов). Другие особенности никнейма можно узнать в соответствующем разделе RFC [1].
Важной особенностью IRC сети является необходимость всех серверов иметь следующую информацию обо всех клиентах: настоящее имя хоста на котором работает клиент, имя пользователя клиента на этом хосте, и сервер, к которому подключен клиент.
Прием/передача сообщений внутри сети
Сообщение в IRC — это команда, состоящая максимум из трех основных частей: префикса (необязательно), команды и параметров команды (которых может быть до 15). Команда должна быть либо валидной командой IRC, либо трехзначным числом, представленным в тексте ASCII.
Один-к-одному. Обычно общение один-к-одному осуществляется только клиентами, поскольку большая часть трафика сервер-сервер не является результатом взаимодействия серверов только друг с другом. Чтобы предоставить клиентам безопасные средства общения друг с другом, требуется, чтобы все серверы могли отправлять сообщение ровно в одном направлении по связующему дереву, чтобы достичь любого клиента. Путь доставляемого сообщения — это кратчайший путь между любыми двумя точками связующего дерева.
Один-ко-многим. Основная цель IRC — предоставить форум, который позволяет легко и эффективно общаться со многими клиентами. IRC имеет несколько средств для достижения этой цели: отправка сообщения списку пользователей, отправка в канал (группу пользователей), отправка конкретному хосту/маске. Подробнее о каналах и списках пользователей можно прочитать в RFC 2811 [3].
Клиент-к-клиенту. Не существует класса сообщений, который позволил бы отправить сообщение другому клиенту напрямую.
Клиент-к-серверу. Большинство команд, которые приводят к изменению информации о состоянии какой-либо части IRC сети (например, членство в канале, режим канала, статус пользователя и т. д.), отправляются на все серверы по умолчанию, и это распределение не может быть изменено клиентом.
Сервер-к-серверу. Большинство сообщений между серверами транслируется на все другие серверы. Исключением является например сообщение к конкретному пользователю, которое доставляется кратчайшим путем, т. е. имеет строгую последовательность промежуточных серверов.
Особенности реализации собственного IRC сервера
При реализации собственного IRC сервера главными вопросами являются способ хранения данных обо всей IRC сети на одном сервере, а также логика приема-обработки-отправки сообщений.
Хранение данных. Необходимо выделить сущности, которые предстоит хранить на сервере и сгруппировать их удобным способом. В IRC это сущности, которые могут подключаться к серверу (другие сервера, и клиенты) и взаимосвязи между этими сущностями (какие клиенты в каких состоят каналах, подключены ли к серверу локально и т. д.). Также возможно хранение метаданных об этих сущностях и взаимосвязях.
Подключения к серверу. Легко заметить, что каждое локальное подключение в программе будет обладать своим собственным идентификатором — номером сокета. При обнаружении нового подключения можно связать его сокет со всеми серверами в подключившейся подсети. При таком подходе, когда нужно будет отправить сообщение конкретному пользователю, мы сможем узнать сокет подсети в котором находится адресат и отправить сообщение в этом направлении.
Взаимосвязи между элементами на сервере хранятся в виде любой структуры данных, которая может хранить в себе ссылки на конкретные элементы. Например для хранения информации о том, какие пользователи к каким принадлежат каналам, можно использовать двусвязный список. Операции добавления и удаления элементов у этой структуры данных имеет сложность вычисления O(1).
Прием и отправка сообщений. Как было сказано выше, сообщения приходят и отправляются на конкретные сокеты. Для эффективной обработки сообщений и написания читаемого программного кода предлагается использовать паттерн объектно ориентированного проектирования «Команда». Суть его заключается в организации обратного вызова к классу, который включает в себя класс-отправитель, и создании структуры, в которой класс-отправитель и класс-получатель не зависят друг от друга напрямую. Другими словами, предлагается реализацию каждой команды вынести в отдельную сущность, которая будет каким-либо образом изменять внутреннее состояние сервера, а сам сервер будет создавать и запускать необходимые команды.
Литература:
- J. Oikarinen, D. Reed Internet Relay Chat Protocol — Текст: электронный // RFC 1459, 1993. — URL: https://tools.ietf.org/html/rfc1459 (дата обращения 17.03.2021)
- C. Kalt Internet Relay Chat: Architecture — Текст: электронный // RFC 2810, 2000. — URL: https://tools.ietf.org/html/rfc2810 (дата обращения 17.03.2021)
- C. Kalt Internet Relay Chat: Channel Management — Текст: электронный // RFC 2811, 2000. — URL: https://tools.ietf.org/html/rfc2811 (дата обращения 17.03.2021)
- C. Kalt Internet Relay Chat: Client Protocol — Текст: электронный // RFC 2812, 2000. — URL: https://tools.ietf.org/html/rfc2812 (дата обращения 17.03.2021)
- C. Kalt Internet Relay Chat: Server Protocol — Текст: электронный // RFC 2813, 2000. — URL: https://tools.ietf.org/html/rfc2813 (дата обращения 17.03.2021)
- Internet Relay Chat — Текст: электронный // Википедия свободная энциклопедия. — URL: https://en.wikipedia.org/wiki/Internet_Relay_Chat (дата обращения 19.03.2021)