/** * a DatagramChannel has data ready - process all the pending packets, whether its for a * rdpserversocket or rdpconnection. */ void processActiveChannel(DatagramChannel dc) throws ClosedChannelException { RDPPacket packet; int count = 0; // read in the packet try { Set<RDPConnection> needsAckConnections = new HashSet<RDPConnection>(); while ((packet = RDPServer.receivePacket(dc)) != null) { if (Log.loggingNet) Log.net( "RDPServer.processActiveChannel: Starting iteration with count of " + count + " packets"); // see if there is a connection already for this packet InetAddress remoteAddr = packet.getInetAddress(); int remotePort = packet.getPort(); int localPort = dc.socket().getLocalPort(); ConnectionInfo conInfo = new ConnectionInfo(remoteAddr, remotePort, localPort); RDPConnection con = RDPServer.getConnection(dc, conInfo); if (con != null) { if (Log.loggingNet) Log.net("RDPServer.processActiveChannel: found an existing connection: " + con); count++; if (processExistingConnection(con, packet)) needsAckConnections.add(con); // Prevent this from blocking getActiveChannels by // putting an upper bound on the number of packets // processed if (count >= 20) break; continue; } else { Log.net("RDPServer.processActiveChannel: did not find an existing connection"); } // there is no connection, // see if there is a socket listening for new connection RDPServerSocket rdpSocket = RDPServer.getRDPSocket(dc); if (rdpSocket != null) { count++; processNewConnection(rdpSocket, packet); return; } return; } // Finally, send out the acks for (RDPConnection con : needsAckConnections) { RDPPacket replyPacket = new RDPPacket(con); con.sendPacketImmediate(replyPacket, false); } } catch (ClosedChannelException ex) { Log.error("RDPServer.processActiveChannel: ClosedChannel " + dc.socket()); throw ex; } finally { if (Log.loggingNet) Log.net("RDPServer.processActiveChannel: Returning after processing " + count + " packets"); } }
/** returns a list of rdpserversockets */ Set<DatagramChannel> getActiveChannels() throws InterruptedException, java.io.IOException { lock.lock(); try { while (channelMap.isEmpty()) { channelMapNotEmpty.await(); } } finally { lock.unlock(); } Set<SelectionKey> readyKeys = null; do { lock.lock(); try { if (!newChannelSet.isEmpty()) { if (Log.loggingNet) Log.net("RDPServer.getActiveChannels: newChannelSet is not null"); Iterator<DatagramChannel> iter = newChannelSet.iterator(); while (iter.hasNext()) { DatagramChannel newDC = iter.next(); iter.remove(); newDC.register(selector, SelectionKey.OP_READ); } } } finally { lock.unlock(); } int numReady = selector.select(); // this is a blocking call - thread safe selectCalls++; if (numReady == 0) { if (Log.loggingNet) Log.net("RDPServer.getActiveChannels: selector returned 0"); continue; } readyKeys = selector.selectedKeys(); if (Log.loggingNet) Log.net( "RDPServer.getActiveChannels: called select - # of ready keys = " + readyKeys.size() + " == " + numReady); } while (readyKeys == null || readyKeys.isEmpty()); lock.lock(); try { // get a datagramchannel that is ready Set<DatagramChannel> activeChannels = new HashSet<DatagramChannel>(); Iterator<SelectionKey> iter = readyKeys.iterator(); while (iter.hasNext()) { SelectionKey key = iter.next(); if (Log.loggingNet) Log.net( "RDPServer.getActiveChannels: matched selectionkey: " + key + ", isAcceptable=" + key.isAcceptable() + ", isReadable=" + key.isReadable() + ", isValid=" + key.isValid() + ", isWritable=" + key.isWritable()); iter.remove(); // remove from the selected key list if (!key.isReadable() || !key.isValid()) { Log.error( "RDPServer.getActiveChannels: Throwing exception: RDPServer: not readable or invalid"); throw new MVRuntimeException("RDPServer: not readable or invalid"); } DatagramChannel dc = (DatagramChannel) key.channel(); activeChannels.add(dc); } if (Log.loggingNet) Log.net( "RDPServer.getActiveChannels: returning " + activeChannels.size() + " active channels"); return activeChannels; } finally { lock.unlock(); } }