at.alladin.rmbt.android.impl.TracerouteAndroidImpl.java Source code

Java tutorial

Introduction

Here is the source code for at.alladin.rmbt.android.impl.TracerouteAndroidImpl.java

Source

/*******************************************************************************
 * Copyright 2015 SPECURE GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package at.alladin.rmbt.android.impl;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.json.JSONException;
import org.json.JSONObject;

import at.alladin.rmbt.util.tools.TracerouteService;

/**
 * 
 * @author lb
 *
 */
public class TracerouteAndroidImpl implements TracerouteService {

    public static final class PingException extends IOException {

        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public PingException(String msg) {
            super(msg);
        }
    }

    public final static class PingDetailImpl implements HopDetail {
        private final int transmitted;
        private final int received;
        private final int errors;
        private final int packetLoss;
        private long time;
        private final String fromIp;

        public final static Pattern PATTERN_PING_PACKET = Pattern.compile(
                "([\\d]*) packets transmitted, ([\\d]*) received, ([+-]?([\\d]*) errors, )?([\\d]*)% packet loss, time ([\\d]*)ms");
        //public final static Pattern PATTERN_FROM_IP =  Pattern.compile("[fF]rom ([\\.:-_\\d\\w\\s\\(\\)]*):(.*time=([\\d\\.]*))?");
        public final static Pattern PATTERN_FROM_IP = Pattern
                .compile("[fF]rom ([\\.\\-_\\d\\w\\s\\(\\)]*)(:|icmp)+(.*time=([\\d\\.]*))?");

        public PingDetailImpl(String pingResult, final long durationNs) {
            System.out.println(pingResult);

            time = durationNs;
            ;
            final Matcher pingPacket = PATTERN_PING_PACKET.matcher(pingResult);

            if (pingPacket.find()) {
                transmitted = Integer.parseInt(pingPacket.group(1));
                received = Integer.parseInt(pingPacket.group(2));
                String errors = pingPacket.group(4);
                if (errors != null) {
                    this.errors = Integer.parseInt(errors);
                } else {
                    this.errors = 0;
                }
                packetLoss = Integer.parseInt(pingPacket.group(5));
            } else {
                transmitted = 0;
                received = 0;
                packetLoss = 0;
                errors = 0;
            }

            final Matcher fromIpMatcher = PATTERN_FROM_IP.matcher(pingResult);
            if (fromIpMatcher.find()) {
                fromIp = fromIpMatcher.group(1);
                String time = fromIpMatcher.group(4);
                if (time != null) {
                    this.time = TimeUnit.NANOSECONDS.convert((int) (Float.parseFloat(time) * 1000f),
                            TimeUnit.MICROSECONDS);
                }
            } else {
                fromIp = "*";
            }

        }

        public long getTime() {
            return time;
        }

        public void setTime(long time) {
            this.time = time;
        }

        public int getTransmitted() {
            return transmitted;
        }

        public int getReceived() {
            return received;
        }

        public int getErrors() {
            return errors;
        }

        public int getPacketLoss() {
            return packetLoss;
        }

        public String getFromIp() {
            return fromIp;
        }

        @Override
        public String toString() {
            return "PingDetail [transmitted=" + transmitted + ", received=" + received + ", errors=" + errors
                    + ", packetLoss=" + packetLoss + ", time=" + (time / 1000000) + "ms, fromIp=" + fromIp + "]";
        }

        public JSONObject toJson() {
            JSONObject json = new JSONObject();
            try {
                json.put("host", fromIp);
                json.put("time", time);
                return json;
            } catch (JSONException e) {
                e.printStackTrace();
                return null;
            }
        }
    }

    private String host;
    private int maxHops;
    private AtomicBoolean isRunning = new AtomicBoolean(false);
    private boolean hasMaxHopsExceeded = true;

    public TracerouteAndroidImpl() {

    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getMaxHops() {
        return maxHops;
    }

    public void setMaxHops(int maxHops) {
        this.maxHops = maxHops;
    }

    public List<HopDetail> call() throws Exception {
        isRunning.set(true);
        List<HopDetail> pingDetailList = new ArrayList<HopDetail>();
        final Runtime runtime = Runtime.getRuntime();

        for (int i = 1; i <= maxHops; i++) {
            if (Thread.interrupted() || !isRunning.get()) {
                throw new InterruptedException();
            }
            final long ts = System.nanoTime();
            final Process mIpAddrProcess = runtime.exec("/system/bin/ping -c 1 -t " + i + " -W2 " + host);
            final String proc = readFromProcess(mIpAddrProcess);
            final PingDetailImpl pingDetail = new PingDetailImpl(proc, System.nanoTime() - ts);
            pingDetailList.add(pingDetail);
            if (pingDetail.getReceived() > 0) {
                hasMaxHopsExceeded = false;
                break;
            }
        }

        return pingDetailList;
    }

    /**
     * stop the ping tool task
     * @return true if task has been stopped or false if it was not running
     */
    public boolean stop() {
        return isRunning.getAndSet(false);
    }

    public static String readFromProcess(Process proc) throws PingException {
        BufferedReader brErr = null;
        BufferedReader br = null;
        StringBuilder sbErr = new StringBuilder();
        StringBuilder sb = new StringBuilder();

        try {
            brErr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
            String currInputLine = null;

            while ((currInputLine = brErr.readLine()) != null) {
                sbErr.append(currInputLine);
                sbErr.append("\n");
            }

            if (sbErr.length() > 0) {
                throw new PingException(sbErr.toString());
            }

            br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            currInputLine = null;

            while ((currInputLine = br.readLine()) != null) {
                sb.append(currInputLine);
                sb.append("\n");
            }
        } catch (PingException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
            }
            try {
                if (brErr != null) {
                    brErr.close();
                }
            } catch (IOException e) {
            }
        }

        return sb.toString();
    }

    @Override
    public boolean hasMaxHopsExceeded() {
        return hasMaxHopsExceeded;
    }
}