Back to project page android_network_discovery.
The source code is released under:
GNU General Public License
If you think the Android project android_network_discovery listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright (C) 2009-2010 Aubort Jean-Baptiste (Rorist) * Licensed under GNU's GPL 2, see README *///from www . j ava2 s.c om /** * Java NIO Documentation: * http://jfarcand.wordpress.com/2006/05/30/tricks-and-tips-with-nio-part-i-why-you-must-handle-op_write * http://jfarcand.wordpress.com/2006/07/06/tricks-and-tips-with-nio-part-ii-why-selectionkey-attach-is-evil/ * http://jfarcand.wordpress.com/2006/07/07/tricks-and-tips-with-nio-part-iii-to-thread-or-not-to-thread/ * http://jfarcand.wordpress.com/2006/07/19/httpweblogs-java-netblog20060719tricks-and-tips-nio-part-iv-meet-selectors/ * http://jfarcand.wordpress.com/2006/09/21/tricks-and-tips-with-nio-part-v-ssl-and-nio-friend-or-foe * http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/transport/socket/nio/ */ package info.lamatricexiste.network; import info.lamatricexiste.network.Utils.Prefs; import java.io.IOException; import java.lang.ref.WeakReference; import java.net.ConnectException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.channels.ClosedSelectorException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Iterator; import android.app.Activity; import android.content.SharedPreferences; import android.os.AsyncTask; import android.preference.PreferenceManager; import android.util.Log; public class AsyncPortscan extends AsyncTask<Void, Object, Void> { private final String TAG = "AsyncPortscan"; private static final int TIMEOUT_SELECT = 300; private static long TIMEOUT_CONNECT = 1000 * 1000000; // ns private static final long TIMEOUT_RW = 3 * 1000 * 1000000; // ns private static final String E_REFUSED = "Connection refused"; private static final String E_TIMEOUT = "The operation timed out"; // TODO: Probe system to send other stuff than strings private static final String[] PROBES = new String[] { "", "\r\n\r\n", "GET / HTTP/1.0\r\n\r\n" }; private static final int MAX_READ = 8 * 1024; private static final int WRITE_PASS = PROBES.length; private static final long WRITE_COOLDOWN = 200 * 1000000; // ns private int rate; private boolean select = true; private Selector selector; protected String ipAddr = null; protected int port_start = 0; protected int port_end = 0; protected int nb_port = 0; private boolean getBanner = false; private ByteBuffer byteBuffer = ByteBuffer.allocate(MAX_READ); private Charset charset = Charset.forName("UTF-8"); public final static int OPEN = 0; public final static int CLOSED = 1; public final static int FILTERED = -1; public final static int UNREACHABLE = -2; public final static int TIMEOUT = -3; protected AsyncPortscan(Activity activity, String host, int _rate) { ipAddr = host; rate = _rate; TIMEOUT_CONNECT = rate * 1000000; // ms to ns // Preferences WeakReference<Activity> mActivity = new WeakReference<Activity>( activity); final Activity d = mActivity.get(); if (d != null) { SharedPreferences prefs = PreferenceManager .getDefaultSharedPreferences(d.getApplicationContext()); getBanner = prefs .getBoolean(Prefs.KEY_BANNER, Prefs.DEFAULT_BANNER); } } @Override protected Void doInBackground(Void... params) { try { int step = 127; Log.i("AsyncPortScan","Executed"); InetAddress ina = InetAddress.getByName(ipAddr); if (nb_port > step) { // FIXME: Selector leaks file descriptors (Dalvik bug) // http://code.google.com/p/android/issues/detail?id=4825 for (int i = port_start; i <= port_end - step; i += step + 1) { if (select) { start(ina, i, i + ((i + step <= port_end - step) ? step : port_end - i)); } } } else { start(ina, port_start, port_end); } } catch (UnknownHostException e) { Log.e(TAG, e.getMessage()); publishProgress(0, UNREACHABLE, null); } return null; } private void start(final InetAddress ina, final int PORT_START, final int PORT_END) { select = true; try { selector = Selector.open(); for (int j = PORT_START; j <= PORT_END; j++) { connectSocket(ina, j); } while (select && selector.keys().size() > 0) { if (selector.select(TIMEOUT_SELECT) > 0) { synchronized (selector.selectedKeys()) { Iterator<SelectionKey> iterator = selector .selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey key = (SelectionKey) iterator.next(); try { if (!key.isValid()) { continue; } // States final Data data = (Data) key.attachment(); if (key.isConnectable()) { if (((SocketChannel) key.channel()) .finishConnect()) { if (getBanner) { key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE); data.state = OPEN; data.start = System.nanoTime(); publishProgress(data.port, OPEN, null); } else { finishKey(key, OPEN); } } } else if (key.isReadable()) { try { byteBuffer.clear(); final int numRead = ((SocketChannel) key .channel()).read(byteBuffer); if (numRead > 0) { String banner = new String( byteBuffer.array()) .substring(0, numRead) .trim(); // Log.v(TAG, "read " + data.port + // " data=" + banner); finishKey(key, OPEN, banner); } else { key.interestOps(SelectionKey.OP_WRITE); } } catch (IOException e) { Log.e(TAG, e.getMessage()); } } else if (key.isWritable()) { key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE); if (System.nanoTime() - data.start > WRITE_COOLDOWN) { if (data.pass < WRITE_PASS) { // Log.v(TAG, "write " + data.port); // write something (blocking) final ByteBuffer bytedata = charset .encode(PROBES[data.pass]); final SocketChannel sock = (SocketChannel) key .channel(); while (bytedata.hasRemaining()) { sock.write(bytedata); } bytedata.clear(); data.start = System.nanoTime(); data.pass++; } else { finishKey(key, OPEN); } } } } catch (ConnectException e) { if (e.getMessage().equals(E_REFUSED)) { finishKey(key, CLOSED); } else if (e.getMessage().equals(E_TIMEOUT)) { finishKey(key, FILTERED); } else { Log.e(TAG, e.getMessage()); e.printStackTrace(); finishKey(key, FILTERED); } } catch (Exception e) { try { Log.e(TAG, e.getMessage()); } catch (java.lang.NullPointerException e1) { e1.printStackTrace(); } finally { e.printStackTrace(); finishKey(key, FILTERED); } } finally { iterator.remove(); } } } } else { // Remove old/non-connected keys final long now = System.nanoTime(); final Iterator<SelectionKey> iterator = selector.keys() .iterator(); while (iterator.hasNext()) { final SelectionKey key = (SelectionKey) iterator.next(); final Data data = (Data) key.attachment(); if (data.state == OPEN && now - data.start > TIMEOUT_RW) { Log.e(TAG, "TIMEOUT=" + data.port); finishKey(key, TIMEOUT); } else if (data.state != OPEN && now - data.start > TIMEOUT_CONNECT) { finishKey(key, TIMEOUT); } } } } } catch (IOException e) { Log.e(TAG, e.getMessage()); } finally { closeSelector(); } } private void connectSocket(InetAddress ina, int port) { // Create the socket try { SocketChannel socket = SocketChannel.open(); socket.configureBlocking(false); socket.connect(new InetSocketAddress(ina, port)); Data data = new Data(); data.port = port; data.start = System.nanoTime(); socket.register(selector, SelectionKey.OP_CONNECT, data); } catch (IOException e) { Log.e(TAG, e.getMessage()); } } protected void onCancelled() { select = false; } private void closeSelector() { try { if (selector.isOpen()) { synchronized (selector.keys()) { Iterator<SelectionKey> iterator = selector.keys() .iterator(); while (iterator.hasNext()) { finishKey((SelectionKey) iterator.next(), FILTERED); } selector.close(); } } } catch (IOException e) { Log.e(TAG, e.getMessage()); } catch (ClosedSelectorException e) { if (e.getMessage() != null) { Log.e(TAG, e.getMessage()); } } } private void finishKey(SelectionKey key, int state) { finishKey(key, state, null); } private void finishKey(SelectionKey key, int state, String banner) { synchronized (key) { if (key == null || !key.isValid()) { return; } closeChannel(key.channel()); Data data = (Data) key.attachment(); publishProgress(data.port, state, banner); key.attach(null); key.cancel(); key = null; } } private void closeChannel(SelectableChannel channel) { if (channel instanceof SocketChannel) { Socket socket = ((SocketChannel) channel).socket(); try { if (!socket.isInputShutdown()) socket.shutdownInput(); } catch (IOException ex) { } try { if (!socket.isOutputShutdown()) socket.shutdownOutput(); } catch (IOException ex) { } try { socket.close(); } catch (IOException ex) { } } try { channel.close(); } catch (IOException ex) { } } // Port private object private static class Data { protected int state = FILTERED; protected int port; protected long start; protected int pass = 0; } }