EMMA Coverage Report (generated Tue Dec 18 20:38:46 CET 2007)
[all classes][cz.vutbr.feec.utko.iptv.ping]

COVERAGE SUMMARY FOR SOURCE FILE [Ping.java]

nameclass, %method, %block, %line, %
Ping.java0%   (0/6)0%   (0/23)0%   (0/658)0%   (0/150)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Ping0%   (0/1)0%   (0/2)0%   (0/130)0%   (0/31)
Ping (): void 0%   (0/1)0%   (0/3)0%   (0/1)
main (String []): void 0%   (0/1)0%   (0/127)0%   (0/30)
     
class Ping$10%   (0/1)0%   (0/2)0%   (0/74)0%   (0/17)
Ping$1 (String): void 0%   (0/1)0%   (0/12)0%   (0/3)
notifyEchoReply (ICMPEchoPacket, byte [], int, byte []): void 0%   (0/1)0%   (0/62)0%   (0/14)
     
class Ping$20%   (0/1)0%   (0/2)0%   (0/52)0%   (0/12)
Ping$2 (int, Ping$Pinger, InetAddress, CountDownLatch, ScheduledThreadPoolExe... 0%   (0/1)0%   (0/21)0%   (0/3)
run (): void 0%   (0/1)0%   (0/31)0%   (0/9)
     
class Ping$Pinger0%   (0/1)0%   (0/11)0%   (0/246)0%   (0/61)
Ping$Pinger (int): void 0%   (0/1)0%   (0/17)0%   (0/5)
Ping$Pinger (int, int, int): void 0%   (0/1)0%   (0/108)0%   (0/26)
close (): void 0%   (0/1)0%   (0/4)0%   (0/2)
computeSendChecksum (InetAddress): void 0%   (0/1)0%   (0/5)0%   (0/2)
getRequestDataLength (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getRequestPacketLength (): int 0%   (0/1)0%   (0/4)0%   (0/1)
ping (InetAddress): long 0%   (0/1)0%   (0/17)0%   (0/5)
receive (): void 0%   (0/1)0%   (0/9)0%   (0/2)
receiveEchoReply (): void 0%   (0/1)0%   (0/29)0%   (0/7)
sendEchoRequest (InetAddress): void 0%   (0/1)0%   (0/45)0%   (0/8)
setEchoReplyListener (Ping$EchoReplyListener): void 0%   (0/1)0%   (0/4)0%   (0/2)
     
class Ping$PingerIPv60%   (0/1)0%   (0/3)0%   (0/57)0%   (0/13)
Ping$PingerIPv6 (int): void 0%   (0/1)0%   (0/25)0%   (0/7)
computeSendChecksum (InetAddress): void 0%   (0/1)0%   (0/19)0%   (0/4)
receive (): void 0%   (0/1)0%   (0/13)0%   (0/2)
     
class Ping$PingerIPv6$ICMPv6ChecksumCalculator0%   (0/1)0%   (0/3)0%   (0/99)0%   (0/19)
Ping$PingerIPv6$ICMPv6ChecksumCalculator (): void 0%   (0/1)0%   (0/4)0%   (0/2)
computeChecksum (byte [], ICMPPacket, byte [], byte []): int 0%   (0/1)0%   (0/28)0%   (0/8)
computeVirtualHeaderTotal (byte [], byte [], int): int 0%   (0/1)0%   (0/67)0%   (0/9)

1/*
2 * $Id: Ping.java 8033 2007-09-03 04:02:36Z dfs $
3 *
4 * Copyright 2004-2007 Daniel F. Savarese
5 * Contact Information: http://www.savarese.org/contact.html
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *     http://www.savarese.org/software/ApacheLicense-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19 
20package cz.vutbr.feec.utko.iptv.ping;
21 
22import java.io.IOException;
23import java.net.InetAddress;
24import java.net.Inet6Address;
25import java.util.concurrent.*;
26 
27import org.savarese.vserv.tcpip.*;
28import org.savarese.rocksaw.net.RawSocket;
29import static org.savarese.rocksaw.net.RawSocket.PF_INET;
30import static org.savarese.rocksaw.net.RawSocket.PF_INET6;
31import static org.savarese.rocksaw.net.RawSocket.getProtocolByName;
32import static org.savarese.vserv.tcpip.ICMPPacket.OFFSET_ICMP_CHECKSUM;
33 
34/**
35 * <p>
36 * The Ping class is a simple demo showing how you can send ICMP echo requests
37 * and receive echo replies using raw sockets. It has been updated to work with
38 * both IPv4 and IPv6.
39 * </p>
40 * 
41 * <p>
42 * Note, this is not a model of good programming. The point of the example is to
43 * show how the RawSocket API calls work. There is much kluginess surrounding
44 * the actual packet and protocol handling, all of which is outside of the scope
45 * of what RockSaw does.
46 * </p>
47 * 
48 * @author <a href="http://www.savarese.org/">Daniel F. Savarese</a>
49 */
50 
51public class Ping {
52 
53        public static interface EchoReplyListener {
54                public void notifyEchoReply(ICMPEchoPacket packet, byte[] data,
55                                int dataOffset, byte[] srcAddress) throws IOException;
56        }
57 
58        public static class Pinger {
59                private static final int TIMEOUT = 10000;
60 
61                protected RawSocket socket;
62                protected ICMPEchoPacket sendPacket, recvPacket;
63                protected int offset, length, dataOffset;
64                protected int requestType, replyType;
65                protected byte[] sendData, recvData, srcAddress;
66                protected int sequence, identifier;
67                protected EchoReplyListener listener;
68 
69                protected Pinger(int id, int protocolFamily, int protocol)
70                                throws IOException {
71                        sequence = 0;
72                        identifier = id;
73                        setEchoReplyListener(null);
74 
75                        sendPacket = new ICMPEchoPacket(1);
76                        recvPacket = new ICMPEchoPacket(1);
77                        sendData = new byte[84];
78                        recvData = new byte[84];
79 
80                        sendPacket.setData(sendData);
81                        recvPacket.setData(recvData);
82                        sendPacket.setIPHeaderLength(5);
83                        recvPacket.setIPHeaderLength(5);
84                        sendPacket.setICMPDataByteLength(56);
85                        recvPacket.setICMPDataByteLength(56);
86 
87                        offset = sendPacket.getIPHeaderByteLength();
88                        dataOffset = offset + sendPacket.getICMPHeaderByteLength();
89                        length = sendPacket.getICMPPacketByteLength();
90 
91                        socket = new RawSocket();
92                        socket.open(protocolFamily, protocol);
93 
94                        try {
95                                socket.setSendTimeout(TIMEOUT);
96                                socket.setReceiveTimeout(TIMEOUT);
97                        } catch (java.net.SocketException se) {
98                                socket.setUseSelectTimeout(true);
99                                socket.setSendTimeout(TIMEOUT);
100                                socket.setReceiveTimeout(TIMEOUT);
101                        }
102                }
103 
104                public Pinger(int id) throws IOException {
105                        this(id, PF_INET, getProtocolByName("icmp"));
106 
107                        srcAddress = new byte[4];
108                        requestType = ICMPPacket.TYPE_ECHO_REQUEST;
109                        replyType = ICMPPacket.TYPE_ECHO_REPLY;
110                }
111 
112                protected void computeSendChecksum(InetAddress host) throws IOException {
113                        sendPacket.computeICMPChecksum();
114                }
115 
116                public void setEchoReplyListener(EchoReplyListener l) {
117                        listener = l;
118                }
119 
120                /**
121                 * Closes the raw socket opened by the constructor. After calling this
122                 * method, the object cannot be used.
123                 */
124                public void close() throws IOException {
125                        socket.close();
126                }
127 
128                public void sendEchoRequest(InetAddress host) throws IOException {
129                        sendPacket.setType(requestType);
130                        sendPacket.setCode(0);
131                        sendPacket.setIdentifier(identifier);
132                        sendPacket.setSequenceNumber(sequence++);
133 
134                        OctetConverter
135                                        .longToOctets(System.nanoTime(), sendData, dataOffset);
136 
137                        computeSendChecksum(host);
138 
139                        socket.write(host, sendData, offset, length);
140                }
141 
142                public void receive() throws IOException {
143                        socket.read(recvData, srcAddress);
144                }
145 
146                public void receiveEchoReply() throws IOException {
147                        do {
148                                receive();
149                        } while (recvPacket.getType() != replyType
150                                        || recvPacket.getIdentifier() != identifier);
151 
152                        if (listener != null)
153                                listener.notifyEchoReply(recvPacket, recvData, dataOffset,
154                                                srcAddress);
155                }
156 
157                /**
158                 * Issues a synchronous ping.
159                 * 
160                 * @param host
161                 *            The host to ping.
162                 * @return The round trip time in nanoseconds.
163                 */
164                public long ping(InetAddress host) throws IOException {
165                        sendEchoRequest(host);
166                        receiveEchoReply();
167 
168                        long end = System.nanoTime();
169                        long start = OctetConverter.octetsToLong(recvData, dataOffset);
170 
171                        return (end - start);
172                }
173 
174                /**
175                 * @return The number of bytes in the data portion of the ICMP ping
176                 *         request packet.
177                 */
178                public int getRequestDataLength() {
179                        return sendPacket.getICMPDataByteLength();
180                }
181 
182                /** @return The number of bytes in the entire IP ping request packet. */
183                public int getRequestPacketLength() {
184                        return sendPacket.getIPPacketLength();
185                }
186        }
187 
188        public static class PingerIPv6 extends Pinger {
189                private static final int IPPROTO_ICMPV6 = 58;
190                private static final int ICMPv6_TYPE_ECHO_REQUEST = 128;
191                private static final int ICMPv6_TYPE_ECHO_REPLY = 129;
192 
193                /**
194                 * Operating system kernels are supposed to calculate the ICMPv6
195                 * checksum for the sender, but Microsoft's IPv6 stack does not do this.
196                 * Nor does it support the IPV6_CHECKSUM socket option. Therefore, in
197                 * order to work on the Windows family of operating systems, we have to
198                 * calculate the ICMPv6 checksum.
199                 */
200                private static class ICMPv6ChecksumCalculator extends IPPacket {
201                        ICMPv6ChecksumCalculator() {
202                                super(1);
203                        }
204 
205                        private int computeVirtualHeaderTotal(byte[] destination,
206                                        byte[] source, int icmpLength) {
207                                int total = 0;
208 
209                                for (int i = 0; i < source.length;)
210                                        total += (((source[i++] & 0xff) << 8) | (source[i++] & 0xff));
211                                for (int i = 0; i < destination.length;)
212                                        total += (((destination[i++] & 0xff) << 8) | (destination[i++] & 0xff));
213 
214                                total += (icmpLength >>> 16);
215                                total += (icmpLength & 0xffff);
216                                total += IPPROTO_ICMPV6;
217 
218                                return total;
219                        }
220 
221                        int computeChecksum(byte[] data, ICMPPacket packet,
222                                        byte[] destination, byte[] source) {
223                                int startOffset = packet.getIPHeaderByteLength();
224                                int checksumOffset = startOffset + OFFSET_ICMP_CHECKSUM;
225                                int ipLength = packet.getIPPacketLength();
226                                int icmpLength = packet.getICMPPacketByteLength();
227 
228                                setData(data);
229 
230                                return _computeChecksum_(startOffset, checksumOffset, ipLength,
231                                                computeVirtualHeaderTotal(destination, source,
232                                                                icmpLength), true);
233                        }
234                }
235 
236                private byte[] localAddress;
237                private ICMPv6ChecksumCalculator icmpv6Checksummer;
238 
239                public PingerIPv6(int id) throws IOException {
240                        // socket.open(protocolFamily,
241                        super(id, PF_INET6, IPPROTO_ICMPV6 /* getProtocolByName("ipv6-icmp") */);
242 
243                        icmpv6Checksummer = new ICMPv6ChecksumCalculator();
244                        srcAddress = new byte[16];
245                        localAddress = new byte[16];
246                        requestType = ICMPv6_TYPE_ECHO_REQUEST;
247                        replyType = ICMPv6_TYPE_ECHO_REPLY;
248                }
249 
250                protected void computeSendChecksum(InetAddress host) throws IOException {
251                        // This is necessary only for Windows, which doesn't implement
252                        // RFC 2463 correctly.
253                        socket.getSourceAddressForDestination(host, localAddress);
254                        icmpv6Checksummer.computeChecksum(sendData, sendPacket, host
255                                        .getAddress(), localAddress);
256                }
257 
258                public void receive() throws IOException {
259                        socket.read(recvData, offset, length, srcAddress);
260                }
261        }
262 
263        public static final void main(String[] args) throws Exception {
264                if (args.length < 1 || args.length > 2) {
265                        System.err.println("usage: Ping host [count]");
266                        System.exit(1);
267                }
268 
269                final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(
270                                2);
271 
272                try {
273                        final InetAddress address = InetAddress.getByName(args[0]);
274                        final String hostname = address.getCanonicalHostName();
275                        final String hostaddr = address.getHostAddress();
276                        final int count;
277                        // Ping programs usually use the process ID for the identifier,
278                        // but we can't get it and this is only a demo.
279                        final int id = 65535;
280                        final Pinger ping;
281 
282                        if (args.length == 2)
283                                count = Integer.parseInt(args[1]);
284                        else
285                                count = 5;
286 
287                        if (address instanceof Inet6Address)
288                                ping = new Ping.PingerIPv6(id);
289                        else
290                                ping = new Ping.Pinger(id);
291 
292                        ping.setEchoReplyListener(new EchoReplyListener() {
293                                StringBuffer buffer = new StringBuffer(128);
294 
295                                public void notifyEchoReply(ICMPEchoPacket packet, byte[] data,
296                                                int dataOffset, byte[] srcAddress) throws IOException {
297                                        long end = System.nanoTime();
298                                        long start = OctetConverter.octetsToLong(data, dataOffset);
299                                        // Note: Java and JNI overhead will be noticeable (100-200
300                                        // microseconds) for sub-millisecond transmission times.
301                                        // The first ping may even show several seconds of delay
302                                        // because of initial JIT compilation overhead.
303                                        double rtt = (double) (end - start) / 1e6;
304 
305                                        buffer.setLength(0);
306                                        buffer.append(packet.getICMPPacketByteLength()).append(
307                                                        " bytes from ").append(hostname).append(" (");
308                                        buffer.append(InetAddress.getByAddress(srcAddress)
309                                                        .toString());
310                                        buffer.append("): icmp_seq=").append(
311                                                        packet.getSequenceNumber()).append(" ttl=").append(
312                                                        packet.getTTL()).append(" time=").append(rtt)
313                                                        .append(" ms");
314                                        System.out.println(buffer.toString());
315                                }
316                        });
317 
318                        System.out.println("PING " + hostname + " (" + hostaddr + ") "
319                                        + ping.getRequestDataLength() + "("
320                                        + ping.getRequestPacketLength() + ") bytes of data).");
321 
322                        final CountDownLatch latch = new CountDownLatch(1);
323 
324                        executor.scheduleAtFixedRate(new Runnable() {
325                                int counter = count;
326 
327                                public void run() {
328                                        try {
329                                                if (counter > 0) {
330                                                        ping.sendEchoRequest(address);
331                                                        if (counter == count)
332                                                                latch.countDown();
333                                                        --counter;
334                                                } else
335                                                        executor.shutdown();
336                                        } catch (IOException ioe) {
337                                                ioe.printStackTrace();
338                                        }
339                                }
340                        }, 0, 1, TimeUnit.SECONDS);
341 
342                        // We wait for first ping to be sent because Windows times out
343                        // with WSAETIMEDOUT if echo request hasn't been sent first.
344                        // POSIX does the right thing and just blocks on the first receive.
345                        // An alternative is to bind the socket first, which should allow a
346                        // receive to be performed frst on Windows.
347                        latch.await();
348 
349                        for (int i = 0; i < count; ++i)
350                                ping.receiveEchoReply();
351 
352                        ping.close();
353                } catch (Exception e) {
354                        executor.shutdown();
355                        e.printStackTrace();
356                }
357        }
358 
359}

[all classes][cz.vutbr.feec.utko.iptv.ping]
EMMA 2.0.5312 EclEmma Fix 1 (C) Vladimir Roubtsov