Всем суток.
Появилась необходимость написать jabber-бота (client) для одного небольшого изолированного сервера.
Java был выбран потому, что его можно запустить под linux'ом, в языке, к сожалению, я пока плаваю.
Но это мне не помешало написать этого самого бота в самые короткие сроки, в качестве xmpp-прослойки был выбрал
Smack API.
О самой проблеме — детально и под катом, вкратце: обработчик рендомно обрабатывает пакеты.
Делаю все как обычно (код упрощен, но ничего другого там нет, что могло бы влиять на работу):
ConnectionConfiguration configuration = new ConnectionConfiguration(SERVER);
configuration.setSASLAuthenticationEnabled(true);
XMPPConnection connection = new XMPPConnection(configuration);
connection.connect();
connection.login(LOGIN, PASSWORD, "systembot");
MultiUserChat muc = new MultiUserChat(connection, TEST_ROOM + "@conference." + SERVER);
muc .join(NICKNAME);
BotChatListener chatListener = new BotChatListener();
muc .addMessageListener(chatListener);
Реализация BotChatListener (находится в том же классе):
public static class BotChatListener implements PacketListener
{
@Override
public void processPacket(Packet packet)
{
Process(packet);
}
}
Подключение проходит успешно, заход в комнату тоже и тут начинается самое интересное, сообщения он принимает, отдает в Process, но тут есть вероятность, не любое сообщение попадает в Process (пытался методом тыка понять, как работает эта вероятность) и после бессонной ночи, бессмысленных правок и изобретений велосипеда — понял, это рендом и ошибка (вероятнее всего) где-то в smack или в моей неправильной конфигурации (
ошибка в коде?). Более того, он может принять пакет, может пройти N-ое время и только тогда пакет попадет в
Process.
Смотрел в стандартном debug от smack, пакет muc'a попадает в принятые пакеты, а потом, через некоторое время, в
Interpreted; если он туда попадает, то Process срабатывает, если нет — последний не срабатывает, то его и в
Interpreted тоже нет и он теряется (
где?), файлы smack'а я не правил, использую версию
3.2.1.
Кстати, чуть не забыл, висит еще кастомный слушатель на самом
connection (его отключаю, проблема с muc остается такой же проблемой, т.е. зависит это не от этого):
Инициализация и кидание слушателя:
ProviderManager pm = ProviderManager.getInstance();
pm.addExtensionProvider(TestEvent.elementname, TestEvent.namespace, new TestEvent.Provider());
...
OnlineListener onlineListener = new OnlineListener();
PacketExtensionFilter onlineFilter = new PacketExtensionFilter(TestEvent.namespace);
connection.addPacketListener(onlineListener, onlineFilter);
Реализация
OnlineListener:
public static class OnlineListener implements PacketListener
{
@Override
public void processPacket(Packet packet)
{
TestEvent e = (TestEvent) packet.getExtension(TestEvent.namespace);
Message message = new Message();
message.setTo(e.getUser().aid + "@" + SERVER);
OnlineEvent response = new OnlineEvent();
message.addExtension(response);
connection.sendPacket(message);
}
}
Реализация расширения:
public class TestEvent implements PacketExtension {
private UserRepresentation user;
public static String namespace = "sometext:event:testevent";
public static String elementname = "event";
public ProfileviewEvent()
{
}
public void setUser(UserRepresentation value) {
user = value;
}
public UserRepresentation getUser() {
return user;
}
public String getElementName() {
return ProfileviewEvent.elementname;
}
public String getNamespace() {
return ProfileviewEvent.namespace;
}
public String toXML() {
StringBuffer buf = new StringBuffer();
buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append("\">");
if(user != null) buf.append(user.toXML());
buf.append("</").append(getElementName()).append(">");
return buf.toString();
}
public static class Provider implements PacketExtensionProvider
{
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
TestEvent extension = new TestEvent();
boolean done = false;
while(!done) {
int eventType = parser.next();
if(eventType == XmlPullParser.START_TAG) {
if(parser.getName().equals("User"))
{
UserRepresentation user = new UserRepresentation();
...
extension.setUser(user);
done = true;
}
}
}
return extension;
}
}
}
Так вот, с этим тоже происходят необычные вещи, он отвечает на сообщение с extension (может и с обычным тоже) — 50 на 50. Есть мнение, что он так же, либо попадает в
Interpreted, либо нет.
Еще раз напомню, что первая проблема самостоятельно существует от второй, они как-то связанны.
_________
Поисковик, конечно, ничего не дал или я мало искал.