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]

name | class, % | method, % | block, % | line, %
--- | --- | --- | --- | ---
Ping.java | 0% (0/6) | 0% (0/23) | 0% (0/658) | 0% (0/150)

### COVERAGE BREAKDOWN BY CLASS AND METHOD

name | class, % | method, % | block, % | line, %
--- | --- | --- | --- | ---
class Ping | 0% (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$1 | 0% (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$2 | 0% (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$Pinger | 0% (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$PingerIPv6 | 0% (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$ICMPv6ChecksumCalculator | 0% (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 |
20 | package cz.vutbr.feec.utko.iptv.ping;
21 |
22 | import java.io.IOException;
23 | import java.net.InetAddress;
24 | import java.net.Inet6Address;
25 | import java.util.concurrent.*;
26 |
27 | import org.savarese.vserv.tcpip.*;
28 | import org.savarese.rocksaw.net.RawSocket;
29 | import static org.savarese.rocksaw.net.RawSocket.PF_INET;
30 | import static org.savarese.rocksaw.net.RawSocket.PF_INET6;
31 | import static org.savarese.rocksaw.net.RawSocket.getProtocolByName;
32 | import 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 |
51 | public 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