package com.kixeye.kixmpp.server;
/*
* #%L
* KIXMPP
* %%
* Copyright (C) 2014 KIXEYE, Inc
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import io.netty.handler.ssl.SslContext;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import io.netty.util.concurrent.Promise;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.junit.Assert;
import org.junit.Test;
import com.kixeye.kixmpp.KixmppJid;
import com.kixeye.kixmpp.client.KixmppClient;
import com.kixeye.kixmpp.client.module.chat.MessageKixmppClientModule;
import com.kixeye.kixmpp.client.module.chat.MessageListener;
import com.kixeye.kixmpp.client.module.muc.MucJoin;
import com.kixeye.kixmpp.client.module.muc.MucKixmppClientModule;
import com.kixeye.kixmpp.client.module.muc.MucListener;
import com.kixeye.kixmpp.client.module.muc.MucMessage;
import com.kixeye.kixmpp.client.module.presence.Presence;
import com.kixeye.kixmpp.client.module.presence.PresenceKixmppClientModule;
import com.kixeye.kixmpp.client.module.presence.PresenceListener;
import com.kixeye.kixmpp.p2p.discovery.ConstNodeDiscovery;
import com.kixeye.kixmpp.server.module.auth.InMemoryAuthenticationService;
import com.kixeye.kixmpp.server.module.auth.SaslKixmppServerModule;
import com.kixeye.kixmpp.server.module.muc.MucHistory;
import com.kixeye.kixmpp.server.module.muc.MucHistoryProvider;
import com.kixeye.kixmpp.server.module.muc.MucKixmppServerModule;
import com.kixeye.kixmpp.server.utils.SocketUtils;
/**
* Tests the {@link KixmppServer}
*
* @author ebahtijaragic
*/
public class KixmppServerTest {
@Test
public void testUserMapping() throws Exception {
try (KixmppServer server = new KixmppServer(new InetSocketAddress(SocketUtils.findAvailableTcpPort()), "testChat",
new InetSocketAddress(SocketUtils.findAvailableTcpPort()), new ConstNodeDiscovery())) {
Assert.assertNotNull(server.start().get(2, TimeUnit.SECONDS));
((InMemoryAuthenticationService) server.module(SaslKixmppServerModule.class).getAuthenticationService()).addUser("testUser", "testPassword");
server.module(MucKixmppServerModule.class).addService("conference").addRoom("someRoom");
try (KixmppClient client = new KixmppClient(SslContext.newClientContext(), KixmppClient.Type.TCP)) {
final LinkedBlockingQueue<Presence> presences = new LinkedBlockingQueue<>();
final LinkedBlockingQueue<MucJoin> mucJoins = new LinkedBlockingQueue<>();
final LinkedBlockingQueue<MucMessage> mucMessages = new LinkedBlockingQueue<>();
Assert.assertNotNull(client.connect("localhost",server.getBindAddress().getPort(), server.getDomain())
.get(2, TimeUnit.SECONDS));
client.module(PresenceKixmppClientModule.class)
.addPresenceListener(new PresenceListener() {
public void handle(Presence presence) {
presences.offer(presence);
}
});
client.module(MucKixmppClientModule.class).addJoinListener(
new MucListener<MucJoin>() {
public void handle(MucJoin event) {
mucJoins.offer(event);
}
});
client.module(MucKixmppClientModule.class).addMessageListener(
new MucListener<MucMessage>() {
public void handle(MucMessage event) {
mucMessages.offer(event);
}
});
Assert.assertNotNull(client.login("testUser", "testPassword", "testResource").get(2, TimeUnit.SECONDS));
client.module(PresenceKixmppClientModule.class).updatePresence(new Presence());
Assert.assertNotNull(server.getChannel(KixmppJid.fromRawJid("testUser@testchat/testResource")));
}
int count = 0;
while (count < 50 && server.getChannel(KixmppJid.fromRawJid("testUser@testchat/testResource")) != null) {
count++;
System.gc();
Thread.sleep(100);
}
Assert.assertNull(server.getChannel(KixmppJid.fromRawJid("testUser@testchat/testResource")));
}
}
@Test
public void testPrivateMessageUsingKixmpp() throws Exception {
try (KixmppServer server = new KixmppServer(new InetSocketAddress(SocketUtils.findAvailableTcpPort()), "testChat",
new InetSocketAddress(SocketUtils.findAvailableTcpPort()), new ConstNodeDiscovery())) {
Assert.assertNotNull(server.start().get(2, TimeUnit.SECONDS));
((InMemoryAuthenticationService) server.module(SaslKixmppServerModule.class).getAuthenticationService()).addUser("testUser1", "testPassword");
((InMemoryAuthenticationService) server.module(SaslKixmppServerModule.class).getAuthenticationService()).addUser("testUser2", "testPassword");
try (KixmppClient client1 = new KixmppClient()) {
final LinkedBlockingQueue<Presence> client1Presences = new LinkedBlockingQueue<>();
final LinkedBlockingQueue<com.kixeye.kixmpp.client.module.chat.Message> client1Messages = new LinkedBlockingQueue<>();
Assert.assertNotNull(client1.connect("localhost",
server.getBindAddress().getPort(), server.getDomain())
.get(2, TimeUnit.SECONDS));
client1.module(PresenceKixmppClientModule.class)
.addPresenceListener(new PresenceListener() {
public void handle(Presence presence) {
client1Presences.offer(presence);
}
});
client1.module(MessageKixmppClientModule.class)
.addMessageListener(new MessageListener() {
public void handle(com.kixeye.kixmpp.client.module.chat.Message message) {
client1Messages.offer(message);
}
});
Assert.assertNotNull(client1.login("testUser1", "testPassword", "testResource").get(2, TimeUnit.SECONDS));
client1.module(PresenceKixmppClientModule.class).updatePresence(new Presence());
Assert.assertNotNull(client1Presences.poll(2, TimeUnit.SECONDS));
try (KixmppClient client2 = new KixmppClient()) {
final LinkedBlockingQueue<Presence> client2Presences = new LinkedBlockingQueue<>();
final LinkedBlockingQueue<com.kixeye.kixmpp.client.module.chat.Message> client2Messages = new LinkedBlockingQueue<>();
Assert.assertNotNull(client2.connect("localhost",
server.getBindAddress().getPort(), server.getDomain())
.get(2, TimeUnit.SECONDS));
client2.module(PresenceKixmppClientModule.class)
.addPresenceListener(new PresenceListener() {
public void handle(Presence presence) {
client2Presences.offer(presence);
}
});
client2.module(MessageKixmppClientModule.class)
.addMessageListener(new MessageListener() {
public void handle(com.kixeye.kixmpp.client.module.chat.Message message) {
client2Messages.offer(message);
}
});
Assert.assertNotNull(client2.login("testUser2", "testPassword", "testResource").get(2, TimeUnit.SECONDS));
client2.module(PresenceKixmppClientModule.class).updatePresence(new Presence());
Assert.assertNotNull(client2Presences.poll(2, TimeUnit.SECONDS));
final String body = UUID.randomUUID().toString().replace("-", "");
client2.module(MessageKixmppClientModule.class).sendMessage(client1.getJid(), body);
com.kixeye.kixmpp.client.module.chat.Message client1Message = client1Messages.poll(2, TimeUnit.SECONDS);
Assert.assertNotNull(client1Message);
Assert.assertEquals(client2.getJid(), client1Message.getFrom());
Assert.assertEquals(client1.getJid().getBaseJid(), client1Message.getTo().getFullJid());
Assert.assertEquals(body, client1Message.getBody());
}
}
}
}
@Test
public void testSimpleUsingKixmpp() throws Exception {
try (KixmppServer server = new KixmppServer(new InetSocketAddress(SocketUtils.findAvailableTcpPort()), "testChat",
new InetSocketAddress(SocketUtils.findAvailableTcpPort()), new ConstNodeDiscovery())) {
Assert.assertNotNull(server.start().get(2, TimeUnit.SECONDS));
((InMemoryAuthenticationService) server.module(SaslKixmppServerModule.class).getAuthenticationService()).addUser("testUser", "testPassword");
server.module(MucKixmppServerModule.class).addService("conference").addRoom("someRoom");
try (KixmppClient client = new KixmppClient(SslContext.newClientContext(), KixmppClient.Type.TCP)) {
final LinkedBlockingQueue<Presence> presences = new LinkedBlockingQueue<>();
final LinkedBlockingQueue<MucJoin> mucJoins = new LinkedBlockingQueue<>();
final LinkedBlockingQueue<MucMessage> mucMessages = new LinkedBlockingQueue<>();
Assert.assertNotNull(client.connect("localhost",
server.getBindAddress().getPort(), server.getDomain())
.get(2, TimeUnit.SECONDS));
client.module(PresenceKixmppClientModule.class)
.addPresenceListener(new PresenceListener() {
public void handle(Presence presence) {
presences.offer(presence);
}
});
client.module(MucKixmppClientModule.class).addJoinListener(
new MucListener<MucJoin>() {
public void handle(MucJoin event) {
mucJoins.offer(event);
}
});
client.module(MucKixmppClientModule.class).addMessageListener(
new MucListener<MucMessage>() {
public void handle(MucMessage event) {
mucMessages.offer(event);
}
});
Assert.assertNotNull(client.login("testUser", "testPassword", "testResource").get(2, TimeUnit.SECONDS));
client.module(PresenceKixmppClientModule.class).updatePresence(new Presence());
Assert.assertNotNull(presences.poll(2, TimeUnit.SECONDS));
client.module(MucKixmppClientModule.class).joinRoom(KixmppJid.fromRawJid("someRoom@conference.testChat"), "testNick");
MucJoin mucJoin = mucJoins.poll(2, TimeUnit.SECONDS);
Assert.assertNotNull(mucJoin);
client.module(MucKixmppClientModule.class).sendRoomMessage(mucJoin.getRoomJid(), "someMessage", "testNick");
MucMessage mucMessage = mucMessages.poll(2, TimeUnit.SECONDS);
Assert.assertNotNull(mucMessage);
Assert.assertEquals("someMessage", mucMessage.getBody());
}
}
}
@Test
public void testSimpleUsingKixmppWithWebSocket() throws Exception {
try (KixmppServer server = new KixmppServer(new InetSocketAddress(SocketUtils.findAvailableTcpPort()), "testChat",
new InetSocketAddress(SocketUtils.findAvailableTcpPort()), new ConstNodeDiscovery())) {
server.enableWebSocket();
Assert.assertNotNull(server.start().get(2, TimeUnit.SECONDS));
((InMemoryAuthenticationService) server.module(SaslKixmppServerModule.class).getAuthenticationService()).addUser("testUser", "testPassword");
server.module(MucKixmppServerModule.class).addService("conference").addRoom("someRoom");
try (KixmppClient client = new KixmppClient(SslContext.newClientContext(), KixmppClient.Type.WEBSOCKET)) {
final LinkedBlockingQueue<Presence> presences = new LinkedBlockingQueue<>();
final LinkedBlockingQueue<MucJoin> mucJoins = new LinkedBlockingQueue<>();
final LinkedBlockingQueue<MucMessage> mucMessages = new LinkedBlockingQueue<>();
Assert.assertNotNull(client.connect("localhost",
server.getWebSocketAddress().getPort(), server.getDomain())
.get(2, TimeUnit.SECONDS));
client.module(PresenceKixmppClientModule.class)
.addPresenceListener(new PresenceListener() {
public void handle(Presence presence) {
presences.offer(presence);
}
});
client.module(MucKixmppClientModule.class).addJoinListener(
new MucListener<MucJoin>() {
public void handle(MucJoin event) {
mucJoins.offer(event);
}
});
client.module(MucKixmppClientModule.class).addMessageListener(
new MucListener<MucMessage>() {
public void handle(MucMessage event) {
mucMessages.offer(event);
}
});
Assert.assertNotNull(client.login("testUser", "testPassword", "testResource").get(2, TimeUnit.SECONDS));
client.module(PresenceKixmppClientModule.class).updatePresence(new Presence());
Assert.assertNotNull(presences.poll(2, TimeUnit.SECONDS));
client.module(MucKixmppClientModule.class).joinRoom(KixmppJid.fromRawJid("someRoom@conference.testChat"), "testNick");
MucJoin mucJoin = mucJoins.poll(2, TimeUnit.SECONDS);
Assert.assertNotNull(mucJoin);
client.module(MucKixmppClientModule.class).sendRoomMessage(mucJoin.getRoomJid(), "someMessage", "testNick");
MucMessage mucMessage = mucMessages.poll(2, TimeUnit.SECONDS);
Assert.assertNotNull(mucMessage);
Assert.assertEquals("someMessage", mucMessage.getBody());
}
}
}
@Test
public void testSimpleUsingKixmppWithHistory() throws Exception {
try (KixmppServer server = new KixmppServer(new InetSocketAddress(SocketUtils.findAvailableTcpPort()), "testChat",
new InetSocketAddress(SocketUtils.findAvailableTcpPort()), new ConstNodeDiscovery())) {
Assert.assertNotNull(server.start().get(2, TimeUnit.SECONDS));
((InMemoryAuthenticationService) server.module(SaslKixmppServerModule.class).getAuthenticationService()).addUser("testUser", "testPassword");
server.module(MucKixmppServerModule.class).addService("conference").addRoom("someRoom");
server.module(MucKixmppServerModule.class).setHistoryProvider(new MucHistoryProvider() {
public Promise<List<MucHistory>> getHistory(KixmppJid roomJid, KixmppJid userJid, Integer maxChars, Integer maxStanzas, Integer seconds, String since) {
Promise<List<MucHistory>> promise = server.createPromise();
List<MucHistory> history = new ArrayList<>(maxStanzas);
for (int i = 0; i < maxStanzas; i++) {
history.add(new MucHistory(KixmppJid.fromRawJid("user" + i + "@" + server.getDomain() + "/computer"), roomJid,
"nick" + i, "message" + i, System.currentTimeMillis()));
}
promise.setSuccess(history);
return promise;
}
});
try (KixmppClient client = new KixmppClient(SslContext.newClientContext(), KixmppClient.Type.TCP)) {
final LinkedBlockingQueue<Presence> presences = new LinkedBlockingQueue<>();
final LinkedBlockingQueue<MucJoin> mucJoins = new LinkedBlockingQueue<>();
final LinkedBlockingQueue<MucMessage> mucMessages = new LinkedBlockingQueue<>();
Assert.assertNotNull(client.connect("localhost",
server.getBindAddress().getPort(), server.getDomain())
.get(2, TimeUnit.SECONDS));
client.module(PresenceKixmppClientModule.class)
.addPresenceListener(new PresenceListener() {
public void handle(Presence presence) {
presences.offer(presence);
}
});
client.module(MucKixmppClientModule.class).addJoinListener(
new MucListener<MucJoin>() {
public void handle(MucJoin event) {
mucJoins.offer(event);
}
});
client.module(MucKixmppClientModule.class).addMessageListener(
new MucListener<MucMessage>() {
public void handle(MucMessage event) {
mucMessages.offer(event);
}
});
Assert.assertNotNull(client.login("testUser", "testPassword", "testResource").get(2, TimeUnit.SECONDS));
client.module(PresenceKixmppClientModule.class).updatePresence(new Presence());
Assert.assertNotNull(presences.poll(2, TimeUnit.SECONDS));
client.module(MucKixmppClientModule.class).joinRoom(KixmppJid.fromRawJid("someRoom@conference.testChat"), "testNick", 5, null, null, null);
MucJoin mucJoin = mucJoins.poll(2, TimeUnit.SECONDS);
Assert.assertNotNull(mucJoin);
int count = 0;
while (mucMessages.poll(2, TimeUnit.SECONDS) != null) {
count++;
}
Assert.assertEquals(5, count);
}
}
}
@Test
public void testSimpleUsingSmack() throws Exception {
try (KixmppServer server = new KixmppServer(new InetSocketAddress(SocketUtils.findAvailableTcpPort()), "testChat",
new InetSocketAddress(SocketUtils.findAvailableTcpPort()), new ConstNodeDiscovery())) {
Assert.assertNotNull(server.start().get(2, TimeUnit.SECONDS));
((InMemoryAuthenticationService) server.module(
SaslKixmppServerModule.class).getAuthenticationService())
.addUser("testUser", "testPassword");
server.module(MucKixmppServerModule.class).addService("conference")
.addRoom("someRoom");
XMPPConnection connection = new XMPPTCPConnection(
new ConnectionConfiguration("localhost", server
.getBindAddress().getPort(), server.getDomain()));
try {
connection.connect();
connection.login("testUser", "testPassword");
final LinkedBlockingQueue<Message> messages = new LinkedBlockingQueue<>();
PacketListener messageListener = new PacketListener() {
public void processPacket(Packet packet)
throws NotConnectedException {
messages.offer((Message) packet);
}
};
MultiUserChat chat = new MultiUserChat(connection,
"someRoom@conference.testChat");
chat.addMessageListener(messageListener);
chat.join("testNick");
chat.sendMessage("hello!");
Message message = messages.poll(2, TimeUnit.SECONDS);
Assert.assertNotNull(message);
if (null == message.getBody()
|| "".equals(message.getBody().trim())) {
message = messages.poll(2, TimeUnit.SECONDS);
Assert.assertNotNull(message);
Assert.assertEquals("hello!", message.getBody());
}
} finally {
connection.disconnect();
}
}
}
}