!7 import java.nio.*; import java.nio.channels.*; static long timeout = 30000+10000; // idle time + latency static ConnectedInstances cI; static ReliableSingleThread rst = new(r update); static int theNumber; static int port = 6000; static Map dataMapper = synchroMap(); static ServerSocketChannel serverChannel; static Selector selector; sclass State { S computerID = "?"; int countSeen = -1; new LineBuffer lineBuffer; // TODO: max length } p { cI = new ConnectedInstances; cI.connected2.onChange(rst); selector = Selector.open(); serverChannel = ServerSocketChannel.open(); serverChannel.configureBlocking(false); InetSocketAddress sockAddr = new InetSocketAddress(port); serverChannel.socket().bind(sockAddr); serverChannel.register(selector, SelectionKey.OP_ACCEPT); thread "Server Accept Loop" { acceptLoop(); } } svoid cleanMeUp() ctex { if (serverChannel != null) serverChannel.close(); } svoid acceptLoop ctex { while licensed { // wait for events selector.select(); Iterator keys = selector.selectedKeys().iterator(); while (keys.hasNext()) { SelectionKey key = keys.next(); keys.remove(); if (!key.isValid()) continue; pcall { if (key.isAcceptable()) acceptOnSocket(key); else if (key.isReadable()) readFromSocket(key); } } } } //accept a connection made to this channel's socket static void acceptOnSocket(SelectionKey key) throws IOException { ServerSocketChannel serverChannel = cast key.channel(); SocketChannel channel = serverChannel.accept(); channel.configureBlocking(false); Socket socket = channel.socket(); SocketAddress remoteAddr = socket.getRemoteSocketAddress(); print("Connected to: " + remoteAddr); // register channel with selector for further IO dataMapper.put(channel, new State); channel.register(selector, SelectionKey.OP_READ); } static void readFromSocket(SelectionKey key) throws IOException { SocketChannel channel = cast key.channel(); ByteBuffer buffer = ByteBuffer.allocate(1024); int numRead = channel.read(buffer); if (numRead == -1) { Socket socket = channel.socket(); SocketAddress remoteAddr = socket.getRemoteSocketAddress(); print("Connection closed by client: " + remoteAddr); State state = dataMapper.get(channel); if (state != null && state.computerID != null) cI.lostConnection(state.computerID); dataMapper.remove(channel); channel.close(); key.cancel(); ret; } S s = new String(buffer.array(), 0, numRead); print("Got data from client: " + s); final State state = dataMapper.get(channel); if (state != null) state.lineBuffer.append(s, voidfunc(S line) { new Matches m; print("Got line: " + line); if (jmatch("computerID=*", line, m)) { if (state.computerID != null || !possibleComputerID($1)) ret; print("Got computer ID: " + $1); state.computerID = $1; cI.gotConnection(state.computerID); } }); } html { ret "Use port " + port; } svoid sendNumber(SocketChannel socket) ctex { State s = dataMapper.get(socket); if (s != null && theNumber != s.countSeen) { s.countSeen = theNumber; print("Sending number to " + s.computerID + ": " + theNumber); socket.write(ByteBuffer.wrap(toUtf8(theNumber + "\n"))); } } svoid update { print("OS Instances update"); if (empty(dataMapper)) ret; int value = cI.value(); //if (value == theNumber) ret; theNumber = value; for (SocketChannel socket : keysList(dataMapper)) pcall { sendNumber(socket); } print("OS Instances update done"); }