diff --git a/ext/rocksaw/lib/tmp.jar b/ext/rocksaw/lib/tmp.jar
deleted file mode 100755
index a2187642..00000000
Binary files a/ext/rocksaw/lib/tmp.jar and /dev/null differ
diff --git a/ext/rocksaw/src/java/org/savarese/rocksaw/net/RawSocket.java b/ext/rocksaw/src/java/org/savarese/rocksaw/net/RawSocket.java
index 7da14268..3c57ed05 100755
--- a/ext/rocksaw/src/java/org/savarese/rocksaw/net/RawSocket.java
+++ b/ext/rocksaw/src/java/org/savarese/rocksaw/net/RawSocket.java
@@ -19,14 +19,13 @@
package org.savarese.rocksaw.net;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.io.InterruptedIOException;
-import java.io.OutputStream;
import java.net.InetAddress;
import java.net.SocketException;
+import net.azib.ipscan.core.LibraryLoader;
+
/**
* The RawSocket class provides a strictly utilitarian API for
* performing I/O with raw sockets. The API is currently crude, but
@@ -79,8 +78,8 @@ public class RawSocket {
native static void __RockSawShutdown();
static {
- // modified to reuse SWT's loading of jni libs from jar file
- loadLibrary("rocksaw");
+ // modified to load jni libs from jar file
+ LibraryLoader.loadLibrary("rocksaw");
if(__RockSawStartup() != 0)
throw new UnsatisfiedLinkError(__getErrorMessage());
@@ -151,41 +150,7 @@ public class RawSocket {
setUseSelectTimeout(false);
}
-
- private static void loadLibrary(String library) {
- String filename = System.mapLibraryName(library);
- String fullFilename = System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + filename;
- try {
- System.load(fullFilename);
- }
- catch (UnsatisfiedLinkError e) {
- try {
- // try to extract
- InputStream is = RawSocket.class.getClassLoader().getResourceAsStream(filename);
- byte[] buffer = new byte[4096];
- OutputStream os = new FileOutputStream(fullFilename);
- int read;
- while ((read = is.read(buffer)) != -1) {
- os.write(buffer, 0, read);
- }
- os.close();
- is.close();
- if (!net.azib.ipscan.config.Platform.WINDOWS) {
- // TODO: change this to new File(fullFilename).setExecutable(true) in case of Java 1.6
- try {
- Runtime.getRuntime ().exec (new String []{"chmod", "755", fullFilename}).waitFor();
- } catch (Throwable t) {}
- }
- System.load(fullFilename);
- }
- catch (IOException ioe) {
- throw new RuntimeException("Unable to extract native library: " + library, ioe);
- }
- }
-
- }
-
-/**
+ /**
* Tests if the socket has been opened.
*
* @return True if the socket is open.
diff --git a/ext/winping/jni/WindowsPinger.c b/ext/winping/jni/WindowsPinger.c
deleted file mode 100755
index 80f7eaea..00000000
--- a/ext/winping/jni/WindowsPinger.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2007 Anton Keks
- */
-
-#include
-
-#include "WindowsPinger.h"
-
-FARPROC IcmpCreateFile;
-
-typedef BOOL (FAR WINAPI *TIcmpCloseHandle)(HANDLE IcmpHandle);
-TIcmpCloseHandle IcmpCloseHandle;
-
-typedef DWORD (FAR WINAPI *TIcmpSendEcho)(
- HANDLE IcmpHandle, /* handle returned from IcmpCreateFile() */
- u_long DestAddress, /* destination IP address (in network order) */
- LPVOID RequestData, /* pointer to buffer to send */
- WORD RequestSize, /* length of data in buffer */
- LPIPINFO RequestOptns, /* see Note 2 */
- LPVOID ReplyBuffer, /* see Note 1 */
- DWORD ReplySize, /* length of reply (must allow at least 1 reply) */
- DWORD Timeout /* time in milliseconds to wait for reply */
-);
-TIcmpSendEcho IcmpSendEcho;
-
-/*
- * Class: net_azib_ipscan_core_net_WindowsPinger
- * Method: nativeIcmpCreateFile
- */
-JNIEXPORT jint JNICALL
-Java_net_azib_ipscan_core_net_WindowsPinger_nativeIcmpCreateFile
-(JNIEnv *env, jclass cls)
-{
- HMODULE hICMP = LoadLibrary("icmp.dll");
- if (!hICMP) {
- // newer versions of Windows should include this one instead
- hICMP = LoadLibrary("iphlpapi.dll");
- }
- if (!hICMP) {
- return -1;
- }
- IcmpCreateFile = (FARPROC)GetProcAddress(hICMP, "IcmpCreateFile");
- IcmpCloseHandle = (TIcmpCloseHandle)GetProcAddress(hICMP, "IcmpCloseHandle");
- IcmpSendEcho = (TIcmpSendEcho)GetProcAddress(hICMP, "IcmpSendEcho");
-
- return IcmpCreateFile();
-}
-
-/*
- * Class: net_azib_ipscan_core_net_WindowsPinger
- * Method: nativeIcmpCloseHandle
- */
-JNIEXPORT jint JNICALL
-Java_net_azib_ipscan_core_net_WindowsPinger_nativeIcmpCloseHandle
-(JNIEnv *env, jclass cls, jint handle)
-{
- return IcmpCloseHandle(handle);
-}
-
-/*
- * Class: net_azib_ipscan_core_net_WindowsPinger
- * Method: nativeIcmpSendEcho
- */
-JNIEXPORT jint JNICALL
-Java_net_azib_ipscan_core_net_WindowsPinger_nativeIcmpSendEcho
-(JNIEnv *env, jclass cls, jint handle,
- jbyteArray address, jbyteArray pingData, jbyteArray replyData, jint timeout)
-{
- DWORD replyCount;
- IPINFO IPInfo;
- jbyte *addrBuf, *pingDataBuf, replyDataBuf;
- jclass replyClass;
- jfieldID fid;
-
- IPInfo.Ttl = 128;
- IPInfo.Tos = 0;
- IPInfo.Flags = 0;
- IPInfo.OptionsSize = 0;
- IPInfo.OptionsData = NULL;
-
- addrBuf = env->GetByteArrayElements(env, address, NULL);
- pingDataBuf = env->GetByteArrayElements(env, pingData, NULL);
- replyDataBuf = env->GetByteArrayElements(env, replyData, NULL);
-
- replyCount = IcmpSendEcho(handle, (DWORD)*addrBuf, pingDataBuf, env->GetArrayLength(pingData) * sizeof(jbyte),
- &IPInfo, replyDataBuf, env->GetArrayLength(replyData), timeout);
-
- env->ReleaseByteArrayElements(env, address, addrBuf, JNI_ABORT);
- env->ReleaseByteArrayElements(env, pingData, pingDataBuf, JNI_ABORT);
- env->ReleaseByteArrayElements(env, replyData, replyDataBuf, NULL);
-
- return replyCount;
-}
diff --git a/ext/winping/lib/winping.dll b/ext/winping/lib/winping.dll
new file mode 100644
index 00000000..0ecd2c57
Binary files /dev/null and b/ext/winping/lib/winping.dll differ
diff --git a/ext/winping/jni/Makefile b/ext/winping/src/Makefile
similarity index 65%
rename from ext/winping/jni/Makefile
rename to ext/winping/src/Makefile
index c77c3aaa..8bebe695 100755
--- a/ext/winping/jni/Makefile
+++ b/ext/winping/src/Makefile
@@ -1,8 +1,13 @@
#
+# This file is a part of Angry IP Scanner source code,
+# see http://www.azib.net/ for more information.
+# Licensed under GPLv2.
+#
# Windows JNI pinger using Microsoft's ICMP.DLL
+# Author: Anton Keks
#
-# Copyright 2007 Anton Keks
-#
+
+DEST = ..\lib
JAVA_INCDIR = $(JDK_HOME)\include
JAVA_INCDIR_PLAF = $(JAVA_INCDIR)\win32
@@ -22,10 +27,10 @@ CLEAN_EXTENSIONS = *.obj *.$(LIBEXTENSION) *.lib *.exp
all: $(LIBWINPING)
.c.obj:
- $(CC) -nologo $(CFLAGS) $(CPPFLAGS) -c $< -o $@
+ $(CC) -nologo $(CFLAGS) $(CPPFLAGS) -c $< -o $(DEST)\$@
$(LIBWINPING): $(OBJ)
- $(CC) -nologo -MD -LD -o $@ $**
+ $(CC) -nologo -MD -LD -o $(DEST)\$@ $**
clean:
del $(CLEAN_EXTENSIONS)
diff --git a/ext/winping/src/WindowsPinger.c b/ext/winping/src/WindowsPinger.c
new file mode 100755
index 00000000..b43c097b
--- /dev/null
+++ b/ext/winping/src/WindowsPinger.c
@@ -0,0 +1,103 @@
+/*
+ * This file is a part of Angry IP Scanner source code,
+ * see http://www.azib.net/ for more information.
+ * Licensed under GPLv2.
+ *
+ * Windows JNI pinger using Microsoft's ICMP.DLL
+ * Author: Anton Keks
+ */
+
+#include
+
+#include "WindowsPinger.h"
+
+
+FARPROC IcmpCreateFile = NULL;
+
+typedef BOOL (FAR WINAPI *TIcmpCloseHandle)(HANDLE IcmpHandle);
+TIcmpCloseHandle IcmpCloseHandle = NULL;
+
+typedef DWORD (FAR WINAPI *TIcmpSendEcho)(
+ HANDLE IcmpHandle, /* handle returned from IcmpCreateFile() */
+ u_long DestAddress, /* destination IP address (in network order) */
+ LPVOID RequestData, /* pointer to buffer to send */
+ WORD RequestSize, /* length of data in buffer */
+ LPVOID RequestOptns, /* see Note 2 */
+ LPVOID ReplyBuffer, /* see Note 1 */
+ DWORD ReplySize, /* length of reply (must allow at least 1 reply) */
+ DWORD Timeout /* time in milliseconds to wait for reply */
+);
+TIcmpSendEcho IcmpSendEcho = NULL;
+
+/*
+ * Class: net_azib_ipscan_core_net_WindowsPinger
+ * Method: nativeIcmpCreateFile
+ */
+JNIEXPORT jint JNICALL
+Java_net_azib_ipscan_core_net_WindowsPinger_nativeIcmpCreateFile
+(JNIEnv *env, jclass cls)
+{
+ // Initialize dlls on first use
+ if (IcmpCreateFile == NULL) {
+ HMODULE hICMP = LoadLibrary("icmp.dll");
+ if (!hICMP) {
+ // newer versions of Windows should include this one instead
+ hICMP = LoadLibrary("iphlpapi.dll");
+ }
+
+ if (!hICMP) {
+ return -1;
+ }
+
+ IcmpCreateFile = (FARPROC) GetProcAddress(hICMP, "IcmpCreateFile");
+ IcmpCloseHandle = (TIcmpCloseHandle) GetProcAddress(hICMP, "IcmpCloseHandle");
+ IcmpSendEcho = (TIcmpSendEcho) GetProcAddress(hICMP, "IcmpSendEcho");
+ }
+
+ return IcmpCreateFile();
+}
+
+/*
+ * Class: net_azib_ipscan_core_net_WindowsPinger
+ * Method: nativeIcmpCloseHandle
+ */
+JNIEXPORT void JNICALL
+Java_net_azib_ipscan_core_net_WindowsPinger_nativeIcmpCloseHandle
+(JNIEnv *env, jclass cls, jint handle)
+{
+ return IcmpCloseHandle((HANDLE)handle);
+}
+
+/*
+ * Class: net_azib_ipscan_core_net_WindowsPinger
+ * Method: nativeIcmpSendEcho
+ */
+
+JNIEXPORT jint JNICALL
+Java_net_azib_ipscan_core_net_WindowsPinger_nativeIcmpSendEcho
+(JNIEnv *env, jclass cls, jint handle, jbyteArray address, jbyteArray pingData, jbyteArray replyData, jint timeout)
+{
+ DWORD replyCount;
+ jbyte *addrBuf, *pingDataBuf, *replyDataBuf;
+ jint pingDataLen, replyDataLen;
+ jclass replyClass;
+ jfieldID fid;
+ u_long ip;
+
+ addrBuf = (*env)->GetByteArrayElements(env, address, NULL);
+ pingDataBuf = (*env)->GetByteArrayElements(env, pingData, NULL);
+ replyDataBuf = (*env)->GetByteArrayElements(env, replyData, NULL);
+
+ pingDataLen = (*env)->GetArrayLength(env, pingData);
+ replyDataLen = (*env)->GetArrayLength(env, replyData);
+
+ ip = *((u_long*)addrBuf);
+ replyCount = IcmpSendEcho((HANDLE)handle, ip, pingDataBuf, pingDataLen,
+ NULL, replyDataBuf, replyDataLen, timeout);
+
+ (*env)->ReleaseByteArrayElements(env, address, addrBuf, JNI_ABORT);
+ (*env)->ReleaseByteArrayElements(env, pingData, pingDataBuf, JNI_ABORT);
+ (*env)->ReleaseByteArrayElements(env, replyData, replyDataBuf, 0);
+
+ return replyCount;
+}
diff --git a/ext/winping/jni/WindowsPinger.h b/ext/winping/src/WindowsPinger.h
similarity index 82%
rename from ext/winping/jni/WindowsPinger.h
rename to ext/winping/src/WindowsPinger.h
index a920f8af..6925c333 100644
--- a/ext/winping/jni/WindowsPinger.h
+++ b/ext/winping/src/WindowsPinger.h
@@ -1,3 +1,12 @@
+/*
+ * This file is a part of Angry IP Scanner source code,
+ * see http://www.azib.net/ for more information.
+ * Licensed under GPLv2.
+ *
+ * Windows JNI pinger using Microsoft's ICMP.DLL
+ * Author: Anton Keks
+ */
+
#include
/* Header for class net_azib_ipscan_core_net_WindowsPinger */
diff --git a/resources/Labels.txt b/resources/Labels.txt
index 64db1133..b7ac351d 100755
--- a/resources/Labels.txt
+++ b/resources/Labels.txt
@@ -134,6 +134,7 @@ list.alive.img=images/list/alive.png
list.addinfo.img=images/list/addinfo.png
pinger.icmp=ICMP Echo
pinger.icmp2=ICMP Echo (Alternative)
+pinger.windows=Windows ICMP.DLL
pinger.udp=UDP packet
pinger.tcp=TCP port probe
opener.web=Web Browser
diff --git a/src/net/azib/ipscan/core/LibraryLoader.java b/src/net/azib/ipscan/core/LibraryLoader.java
new file mode 100644
index 00000000..ae9e72e9
--- /dev/null
+++ b/src/net/azib/ipscan/core/LibraryLoader.java
@@ -0,0 +1,64 @@
+/**
+ * This file is a part of Angry IP Scanner source code,
+ * see http://www.azib.net/ for more information.
+ * Licensed under GPLv2.
+ */
+
+package net.azib.ipscan.core;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Utility class for loading of JNI libraries from jar files.
+ *
+ * @author Anton Keks
+ */
+public class LibraryLoader {
+
+ /**
+ * Loads native library from the jar file (storing it in the temp dir)
+ * @param library JNI library name
+ */
+ public static void loadLibrary(String library) {
+ String filename = System.mapLibraryName(library);
+ String fullFilename = System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + filename;
+ try {
+ // try to load from the temp dir (in case it is already there)
+ System.load(fullFilename);
+ }
+ catch (UnsatisfiedLinkError err2) {
+ try {
+ // try to extract from the jar
+ InputStream is = LibraryLoader.class.getClassLoader().getResourceAsStream(filename);
+ if (is == null) {
+ throw new IOException(filename + " not found in the jar file (classpath)");
+ }
+ byte[] buffer = new byte[4096];
+ OutputStream os = new FileOutputStream(fullFilename);
+ int read;
+ while ((read = is.read(buffer)) != -1) {
+ os.write(buffer, 0, read);
+ }
+ os.close();
+ is.close();
+ if (!net.azib.ipscan.config.Platform.WINDOWS) {
+ // TODO: change this to new File(fullFilename).setExecutable(true) in case of
+ // Java 1.6
+ try {
+ Runtime.getRuntime().exec(new String[] { "chmod", "755", fullFilename }).waitFor();
+ }
+ catch (Throwable t) {
+ }
+ }
+ System.load(fullFilename);
+ }
+ catch (IOException ioe) {
+ throw new RuntimeException("Unable to extract native library: " + library, ioe);
+ }
+ }
+ }
+
+}
diff --git a/src/net/azib/ipscan/core/net/ICMPPinger.java b/src/net/azib/ipscan/core/net/ICMPPinger.java
index 6e73718d..54cbccc6 100644
--- a/src/net/azib/ipscan/core/net/ICMPPinger.java
+++ b/src/net/azib/ipscan/core/net/ICMPPinger.java
@@ -25,7 +25,7 @@ import org.savarese.vserv.tcpip.OctetConverter;
*/
public class ICMPPinger implements Pinger {
- static final Logger LOG = Logger.getLogger(ICMPPinger.class.getName());
+ private static final Logger LOG = Logger.getLogger(ICMPPinger.class.getName());
private int timeout;
diff --git a/src/net/azib/ipscan/core/net/PingerRegistryImpl.java b/src/net/azib/ipscan/core/net/PingerRegistryImpl.java
index 02dee4c0..09dc6494 100755
--- a/src/net/azib/ipscan/core/net/PingerRegistryImpl.java
+++ b/src/net/azib/ipscan/core/net/PingerRegistryImpl.java
@@ -14,12 +14,13 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import net.azib.ipscan.config.GlobalConfig;
+import net.azib.ipscan.config.Platform;
import net.azib.ipscan.fetchers.FetcherException;
/**
* PingerRegistryImpl
*
- * @author Anton Keks Keks
+ * @author Anton Keks
*/
public class PingerRegistryImpl implements PingerRegistry {
@@ -34,6 +35,10 @@ public class PingerRegistryImpl implements PingerRegistry {
this.globalConfig = globalConfig;
pingers = new LinkedHashMap>();
+ if (Platform.WINDOWS) {
+ // this will be the preferred choice for Windows users
+ pingers.put("pinger.windows", WindowsPinger.class);
+ }
pingers.put("pinger.icmp", ICMPSharedPinger.class);
pingers.put("pinger.icmp2", ICMPPinger.class);
pingers.put("pinger.udp", UDPPinger.class);
diff --git a/src/net/azib/ipscan/core/net/WindowsPinger.java b/src/net/azib/ipscan/core/net/WindowsPinger.java
index d2de107a..09eb0d2e 100644
--- a/src/net/azib/ipscan/core/net/WindowsPinger.java
+++ b/src/net/azib/ipscan/core/net/WindowsPinger.java
@@ -8,10 +8,13 @@ package net.azib.ipscan.core.net;
import java.io.IOException;
import java.net.InetAddress;
+import net.azib.ipscan.core.LibraryLoader;
+
/**
* Windows-only pinger that uses Microsoft's ICMP.DLL for its job.
+ *
* This pinger exists to provide adequate pinging to Windows users,
- * because Microsoft has removed raw socket support from consumer
+ * because Microsoft has removed Raw Socket support from consumer
* versions of Windows since XP SP2.
*
* @author Anton Keks
@@ -19,12 +22,13 @@ import java.net.InetAddress;
public class WindowsPinger implements Pinger {
private int timeout;
+ private boolean libraryLoaded;
public WindowsPinger(int timeout) {
this.timeout = timeout;
- }
-
- public void close() throws IOException {
+ if (!libraryLoaded) {
+ LibraryLoader.loadLibrary("winping");
+ }
}
public PingResult ping(InetAddress address, int count) throws IOException {
@@ -34,15 +38,22 @@ public class WindowsPinger implements Pinger {
byte[] replyData = new byte[56 + 100];
int handle = nativeIcmpCreateFile();
+ if (handle < 0) {
+ throw new IOException("Unable to create Windows native ICMP handle");
+ }
+
try {
// send a bunch of packets
for (int i = 1; i <= count; i++) {
if (nativeIcmpSendEcho(handle, address.getAddress(), pingData, replyData, timeout) > 0) {
- /*if (replyData.status == 11000) {
- result.addReply(replyData.roundTripTime);
- result.setTTL(replyData.ttl);
- }*/
+ int status = replyData[4] + (replyData[5]<<8) + (replyData[6]<<16) + (replyData[7]<<24);
+ if (status == 0) {
+ int roundTripTime = replyData[8] + (replyData[9]<<8) + (replyData[10]<<16) + (replyData[11]<<24);
+ int timeToLive = replyData[20] & 0xFF;
+ result.addReply(roundTripTime);
+ result.setTTL(timeToLive);
+ }
}
}
}
@@ -53,9 +64,25 @@ public class WindowsPinger implements Pinger {
return result;
}
+ /**
+ * Wrapper for Microsoft's
+ * {@linkplain http://msdn2.microsoft.com/en-US/library/aa366045.aspx IcmpCreateFile}
+ */
private native static int nativeIcmpCreateFile();
+ /**
+ * Wrapper for Microsoft's
+ * {@linkplain http://msdn2.microsoft.com/EN-US/library/aa366050.aspx IcmpSendEcho}
+ */
private native static int nativeIcmpSendEcho(int handle, byte[] address, byte[] pingData, byte[] replyData, int timeout);
+ /**
+ * Wrapper for Microsoft's IcmpCreateFile:
+ * {@linkplain http://msdn2.microsoft.com/en-us/library/Aa366043.aspx IcmpCloseHandle}
+ */
private native static void nativeIcmpCloseHandle(int handle);
+
+ public void close() throws IOException {
+ // not needed in this pinger
+ }
}