/*
* Copyright (c) 2013. Patrick Valsecchi.
* See accompanying LICENSE file for details about the License.
*/
package ch.thus.javamqtt;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.util.Iterator;
public class MqttServer {
private static final Logger logger = Logger.getLogger(MqttServer.class);
private final Selector selector;
private final MqttServerRepo repository = new MqttServerRepo();
public MqttServer(int port) throws IOException {
selector = SelectorProvider.provider().openSelector();
final ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false);
serverChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
final InetSocketAddress isa = new InetSocketAddress(port);
serverChannel.socket().bind(isa);
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
logger.info("MQTT server listening on port " + port);
}
private void run() {
//noinspection InfiniteLoopStatement
while (true) {
try {
selector.select();
final Iterator<SelectionKey> it = selector.selectedKeys().iterator();
while (it.hasNext()) {
final SelectionKey key = it.next();
if (key.isAcceptable()) {
accept(key);
} else {
if (key.isReadable()) {
read(key);
}
if (key.isValid() && key.isWritable()) {
write(key);
}
}
it.remove();
}
} catch (IOException e) {
logger.warn("Error handling communication", e);
}
}
}
private void accept(SelectionKey key) throws IOException {
final ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
final SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
socketChannel.setOption(StandardSocketOptions.TCP_NODELAY, true);
MqttServerConnection con = new MqttServerConnection(repository, socketChannel);
SelectionKey newKey = socketChannel.register(selector, SelectionKey.OP_READ, con);
con.setKey(newKey);
if (logger.isDebugEnabled()) {
logger.debug("Got a new connection");
}
}
private void read(SelectionKey key) throws IOException {
((MqttServerConnection) key.attachment()).readyRead();
}
private void write(SelectionKey key) throws IOException {
((MqttServerConnection) key.attachment()).readyWrite();
}
public static void main(String[] args) throws IOException {
MqttServer server = new MqttServer(1883);
server.run();
}
}