com.packetsender.android.PacketListenerService.java Source code

Java tutorial

Introduction

Here is the source code for com.packetsender.android.PacketListenerService.java

Source

//  Copyright (c) 2014 Dan Nagle. All rights reserved.
//
// Licensed MIT: https://github.com/dannagle/PacketSender-Android
package com.packetsender.android;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.NetworkOnMainThreadException;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.text.format.DateFormat;
import android.util.Log;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.BindException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.Channel;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;
import java.util.Set;

public class PacketListenerService extends IntentService {

    private NotificationManager mNM;
    private final int NOTIFICATIONID = 100;
    private int listenportTCP = 5000;
    private int listenportUDP = 5000;
    private Notification updateComplete;
    private int packetCounter = 0;
    private PendingIntent contentIntent;
    private Runnable shutdownListener;
    private Runnable sendListener;

    private ServerSocketChannel tcpserver;
    private DatagramChannel udpserver;
    private final Handler mHandler = new Handler();

    private DataStorage dataStore;

    public static final String PARAM_IN_MSG = "imsg";
    public static final String PARAM_OUT_MSG = "omsg";

    public PacketListenerService() {
        super("PacketListenerService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        dataStore = new DataStorage(getSharedPreferences(DataStorage.PREFS_SETTINGS_NAME, 0),
                getSharedPreferences(DataStorage.PREFS_SAVEDPACKETS_NAME, 0),
                getSharedPreferences(DataStorage.PREFS_SERVICELOG_NAME, 0),
                getSharedPreferences(DataStorage.PREFS_MAINTRAFFICLOG_NAME, 0));

        listenportTCP = dataStore.getTCPPort();
        listenportUDP = dataStore.getUDPPort();
        Log.i("service", DataStorage.FILE_LINE("TCP: " + listenportTCP + " / UDP: " + listenportUDP));

        Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);

        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

        contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, 0);

        startNotification();

        CharsetEncoder encoder = Charset.forName("US-ASCII").newEncoder();
        ByteBuffer response = null;
        try {
            response = encoder.encode(CharBuffer.wrap("response"));
        } catch (CharacterCodingException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        try {

            SocketAddress localportTCP = new InetSocketAddress(listenportTCP);
            SocketAddress localportUDP = new InetSocketAddress(listenportUDP);

            tcpserver = ServerSocketChannel.open();
            tcpserver.socket().bind(localportTCP);

            udpserver = DatagramChannel.open();
            udpserver.socket().bind(localportUDP);

            tcpserver.configureBlocking(false);
            udpserver.configureBlocking(false);

            Selector selector = Selector.open();

            tcpserver.register(selector, SelectionKey.OP_ACCEPT);
            udpserver.register(selector, SelectionKey.OP_READ);

            ByteBuffer receiveBuffer = ByteBuffer.allocate(1024);
            receiveBuffer.clear();

            shutdownListener = new Runnable() {
                public void run() {

                    if (false) {

                        try {
                            tcpserver.close();
                        } catch (IOException e) {
                        }
                        try {
                            udpserver.close();
                        } catch (IOException e) {
                        }
                        stopSelf();
                    } else {
                        mHandler.postDelayed(shutdownListener, 2000);

                    }

                }
            };

            sendListener = new Runnable() {
                public void run() {

                    //Packet fetchedPacket = mDbHelper.needSendPacket();
                    Packet[] fetchedPackets = dataStore.fetchAllServicePackets();

                    if (fetchedPackets.length > 0) {
                        dataStore.clearServicePackets();
                        Log.d("service",
                                DataStorage.FILE_LINE("sendListener found " + fetchedPackets.length + " packets"));

                        for (int i = 0; i < fetchedPackets.length; i++) {
                            Packet fetchedPacket = fetchedPackets[i];
                            Log.d("service", DataStorage.FILE_LINE("send packet " + fetchedPacket.toString()));

                        }

                        new SendPacketsTask().execute(fetchedPackets);
                    }

                    mHandler.postDelayed(sendListener, 2000);

                }
            };

            //start shutdown listener
            mHandler.postDelayed(shutdownListener, 2000);

            //start send listener
            mHandler.postDelayed(sendListener, 5000);

            while (true) {
                try { // Handle per-connection problems below
                      // Wait for a client to connect
                    Log.d("service", DataStorage.FILE_LINE("waiting for connection"));
                    selector.select();
                    Log.d("service", DataStorage.FILE_LINE("client connection"));

                    Set keys = selector.selectedKeys();

                    for (Iterator i = keys.iterator(); i.hasNext();) {

                        SelectionKey key = (SelectionKey) i.next();
                        i.remove();

                        Channel c = (Channel) key.channel();

                        if (key.isAcceptable() && c == tcpserver) {

                            SocketChannel client = tcpserver.accept();

                            if (client != null) {

                                Socket tcpSocket = client.socket();
                                packetCounter++;

                                DataInputStream in = new DataInputStream(tcpSocket.getInputStream());

                                byte[] buffer = new byte[1024];
                                int received = in.read(buffer);
                                byte[] bufferConvert = new byte[received];
                                System.arraycopy(buffer, 0, bufferConvert, 0, bufferConvert.length);

                                Packet storepacket = new Packet();
                                storepacket.tcpOrUdp = "TCP";
                                storepacket.fromIP = tcpSocket.getInetAddress().getHostAddress();

                                storepacket.toIP = "You";
                                storepacket.fromPort = tcpSocket.getPort();
                                storepacket.port = tcpSocket.getLocalPort();
                                storepacket.data = bufferConvert;

                                UpdateNotification("TCP:" + storepacket.toAscii(), "From " + storepacket.fromIP);

                                Log.i("service", DataStorage.FILE_LINE("Got TCP"));
                                //dataStore.SavePacket(storepacket);

                                /*
                                Intent tcpIntent = new Intent();
                                tcpIntent.setAction(ResponseReceiver.ACTION_RESP);
                                tcpIntent.addCategory(Intent.CATEGORY_DEFAULT);
                                tcpIntent.putExtra(PARAM_OUT_MSG, storepacket.name);
                                sendBroadcast(tcpIntent);
                                */

                                storepacket.nowMe();
                                dataStore.saveTrafficPacket(storepacket);
                                Log.d("service", DataStorage.FILE_LINE("sendBroadcast"));

                                if (false) //mDbHelper.getSettings(PSDbAdapter.KEY_SETTINGS_SENDRESPONSE).equalsIgnoreCase("Yes"))
                                {
                                    storepacket = new Packet();
                                    storepacket.name = dataStore.currentTimeStamp();
                                    ;
                                    storepacket.tcpOrUdp = "TCP";
                                    storepacket.fromIP = "You";
                                    storepacket.toIP = tcpSocket.getInetAddress().getHostAddress();
                                    storepacket.fromPort = tcpSocket.getLocalPort();
                                    storepacket.port = tcpSocket.getPort();
                                    // storepacket.data = Packet.toBytes(mDbHelper.getSettings(PSDbAdapter.KEY_SETTINGS_SENDRESPONSETEXT));

                                    storepacket.nowMe();
                                    dataStore.saveTrafficPacket(storepacket);
                                    Log.d("service", DataStorage.FILE_LINE("sendBroadcast"));

                                    client.write(response); // send response
                                }

                                client.close(); // close connection
                            }
                        } else if (key.isReadable() && c == udpserver) {

                            DatagramSocket udpSocket;
                            DatagramPacket udpPacket;

                            byte[] buffer = new byte[2048];
                            // Create a packet to receive data into the buffer
                            udpPacket = new DatagramPacket(buffer, buffer.length);

                            udpSocket = udpserver.socket();

                            receiveBuffer.clear();

                            InetSocketAddress clientAddress = (InetSocketAddress) udpserver.receive(receiveBuffer);

                            if (clientAddress != null) {

                                String fromAddress = clientAddress.getAddress().getHostAddress();

                                packetCounter++;

                                int received = receiveBuffer.position();
                                byte[] bufferConvert = new byte[received];

                                System.arraycopy(receiveBuffer.array(), 0, bufferConvert, 0, bufferConvert.length);

                                Packet storepacket = new Packet();
                                storepacket.tcpOrUdp = "UDP";
                                storepacket.fromIP = clientAddress.getAddress().getHostAddress();

                                storepacket.toIP = "You";
                                storepacket.fromPort = clientAddress.getPort();
                                storepacket.port = udpSocket.getLocalPort();
                                storepacket.data = bufferConvert;

                                UpdateNotification("UDP:" + storepacket.toAscii(), "From " + storepacket.fromIP);

                                //dataStore.SavePacket(storepacket);
                                storepacket.nowMe();
                                dataStore.saveTrafficPacket(storepacket);
                                Log.d("service", DataStorage.FILE_LINE("sendBroadcast"));

                                if (false)//mDbHelper.getSettings(PSDbAdapter.KEY_SETTINGS_SENDRESPONSE).trim().equalsIgnoreCase("Yes"))
                                {
                                    storepacket = new Packet();
                                    storepacket.name = dataStore.currentTimeStamp();
                                    ;
                                    storepacket.tcpOrUdp = "UDP";
                                    storepacket.fromIP = "You";
                                    storepacket.toIP = clientAddress.getAddress().getHostAddress();
                                    storepacket.fromPort = udpSocket.getLocalPort();
                                    storepacket.port = clientAddress.getPort();
                                    // storepacket.data = Packet.toBytes(mDbHelper.getSettings(PSDbAdapter.KEY_SETTINGS_SENDRESPONSETEXT));

                                    //dataStore.SavePacket(storepacket);
                                    udpserver.send(response, clientAddress);
                                    storepacket.nowMe();
                                    dataStore.saveTrafficPacket(storepacket);
                                    Log.d("service", DataStorage.FILE_LINE("sendBroadcast"));

                                }
                            }
                        }
                    }
                } catch (java.io.IOException e) {
                    Log.i("service", DataStorage.FILE_LINE("IOException "));
                } catch (Exception e) {
                    Log.w("service", DataStorage.FILE_LINE("Fatal Error: " + Log.getStackTraceString(e)));
                }
            }
        } catch (BindException e) {

            //mDbHelper.putServiceError("Error binding to port");
            dataStore.putToast("Port already in use.");
            Log.w("service", DataStorage.FILE_LINE("Bind Exception: " + Log.getStackTraceString(e)));

        } catch (Exception e) {
            //mDbHelper.putServiceError("Fatal Error starting service");
            Log.w("service", DataStorage.FILE_LINE("Startup error: " + Log.getStackTraceString(e)));
        }

        stopNotification();

    }

    public void onDestroy() {

        try {
            Log.w("service", DataStorage.FILE_LINE("Closing connections"));
            tcpserver.close();
            udpserver.close();
        } catch (IOException e) {
            Log.w("service", DataStorage.FILE_LINE("IOException error: " + Log.getStackTraceString(e)));
        } catch (NullPointerException e) {
            Log.w("service", DataStorage.FILE_LINE("NullPointerException error: " + Log.getStackTraceString(e)));
        }

        stopNotification();

    }

    public void startNotification() {

        UpdateNotification("TCP: " + listenportTCP + " / UDP: " + listenportUDP, "Packet Sender Active");

    }

    public void stopNotification() {

        mNM.cancelAll();

    }

    public void UpdateNotification(String title, String subject) {

        Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.drawable.ic_launcher_status24).setLargeIcon(bm).setContentTitle(title)
                .setTicker(title).setContentText(subject);

        Intent notificationIntent = new Intent(this, MainActivity.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);
        builder.setContentIntent(contentIntent);

        // Add as notification
        mNM = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        mNM.notify(NOTIFICATIONID, builder.build());

    }

    private class SendPacketsTask extends AsyncTask<Packet, Void, Void> {
        // Do the long-running work in here
        protected Void doInBackground(Packet... params) {

            Log.d("SendPacketsTask", DataStorage.FILE_LINE("length" + params.length));

            Packet fetchedPacket = params[0];
            Log.d("SendPacketsTask", DataStorage.FILE_LINE("send packet " + fetchedPacket.toString()));

            //if(1+1 == 2) return null;
            if (fetchedPacket.tcpOrUdp.equalsIgnoreCase("tcp")) {
                UpdateNotification("Send TCP: " + fetchedPacket.toIP, ":" + fetchedPacket.port);

            } else {
                UpdateNotification("Send UDP: " + fetchedPacket.toIP, ":" + fetchedPacket.port);

                //dataStore.SavePacket(storepacket);
                try {

                    ByteBuffer buf = ByteBuffer.allocate(fetchedPacket.data.length);
                    buf.clear();
                    buf.put(fetchedPacket.data);
                    buf.flip();

                    udpserver.send(buf, new InetSocketAddress(fetchedPacket.toIP, fetchedPacket.port));

                    fetchedPacket.fromIP = "You";
                    fetchedPacket.nowMe();
                    dataStore.saveTrafficPacket(fetchedPacket);
                    Log.d("service", DataStorage.FILE_LINE("sendBroadcast"));

                } catch (UnknownHostException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                return null;

            }

            try {
                Socket clientSocket;
                InetSocketAddress translateSocket = new InetSocketAddress(fetchedPacket.toIP, fetchedPacket.port);
                clientSocket = new Socket(translateSocket.getHostName(), translateSocket.getPort());
                clientSocket.setSoTimeout(2000); // 2 second timeout

                DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());

                DataInputStream in = new DataInputStream(clientSocket.getInputStream());

                out.write(fetchedPacket.data);

                Packet savePacket = fetchedPacket.duplicate();
                savePacket.nowMe();
                savePacket.fromIP = "You";
                fetchedPacket.nowMe();
                dataStore.saveTrafficPacket(savePacket);
                Log.d("service", DataStorage.FILE_LINE("sendBroadcast"));

                byte[] buffer = new byte[1024];
                int received = in.read(buffer);
                if (received > 0) {
                    byte[] bufferConvert = new byte[received];
                    System.arraycopy(buffer, 0, bufferConvert, 0, received);
                    Log.i("service", DataStorage.FILE_LINE("FROM SERVER: " + Packet.toHex(bufferConvert)));

                    savePacket = fetchedPacket.duplicate();
                    savePacket.nowMe();
                    savePacket.data = bufferConvert;
                    savePacket.fromIP = fetchedPacket.toIP;
                    savePacket.fromPort = fetchedPacket.port;
                    savePacket.toIP = "You";
                    savePacket.port = fetchedPacket.fromPort;

                    fetchedPacket.nowMe();
                    dataStore.saveTrafficPacket(savePacket);
                    Log.d("service", DataStorage.FILE_LINE("sendBroadcast"));

                }

                out.close();
                in.close();
                clientSocket.close();

            } catch (SocketTimeoutException e) {
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                e.printStackTrace(pw);
                Log.i("service", DataStorage.FILE_LINE("SocketTimeoutException: " + sw.toString()));

            } catch (NetworkOnMainThreadException e) {
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                e.printStackTrace(pw);
                Log.w("service", DataStorage.FILE_LINE("NetworkOnMainThreadException: " + sw.toString()));

            } catch (UnknownHostException e) {
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                e.printStackTrace(pw);
                Log.i("service", DataStorage.FILE_LINE("UnknownHostException: " + sw.toString()));
                Log.i("service", DataStorage.FILE_LINE("Saving the error to packet."));
                fetchedPacket.errorString = "Unknown host";
                fetchedPacket.nowMe();
                dataStore.saveTrafficPacket(fetchedPacket);
            } catch (IOException e) {
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                e.printStackTrace(pw);
                Log.w("service", DataStorage.FILE_LINE("IOException: " + sw.toString())); //failed to connect error.
                Log.i("service", DataStorage.FILE_LINE("Saving the error to packet."));
                fetchedPacket.errorString = "Connection error";
                fetchedPacket.nowMe();
                dataStore.saveTrafficPacket(fetchedPacket);

            } catch (Exception e) {
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                e.printStackTrace(pw);
                Log.w("service", DataStorage.FILE_LINE("Exception: " + sw.toString()));

            }

            return null;
        }

        protected void onProgressUpdate() {
            //setProgressPercent(progress[0]);
        }

        protected void onPostExecute(boolean result) {
            //showDialog("Downloaded " + result + " bytes");
        }
    }

}