Add getHardwareAddress to the NetworkAddress service that wraps NetworkInterface.getHardwareAddress if it exists otherwise via a JNI.

cusax-fix
Sebastien Vincent 16 years ago
parent 5fba65be8c
commit fbaa48424b

@ -468,6 +468,60 @@
</cc>
</target>
<!-- compile hwaddressretriever library -->
<target name="hwaddressretriever" description="Build hwaddressretriever shared library" depends="init-native,hwaddressretriever-windows"
unless="is.running.windows">
<cc outtype="shared" name="gcc" outfile="${native_install_dir}/hwaddressretriever" objdir="${obj}">
<!-- common compiler flags -->
<compilerarg value="-Wall" />
<compilerarg value="-O2" />
<fileset dir="${src}/native/hwaddressretriever" includes="net*.c HardwareAddressRetriever_unix.c" />
<!-- Linux specific flags -->
<compilerarg value="-m32" if="cross_32" unless="is.running.macos" />
<compilerarg value="-m64" if="cross_64" unless="is.running.macos" />
<compilerarg value="-I${system.JAVA_HOME}/include" if="is.running.linux" />
<compilerarg value="-I${system.JAVA_HOME}/include/linux" if="is.running.linux" />
<linkerarg value="-m32" if="cross_32" unless="is.running.macos" />
<linkerarg value="-m64" if="cross_64" unless="is.running.macos" />
<!-- Mac OS X specific flags -->
<compilerarg value="-arch" if="is.running.macos" />
<compilerarg value="x86_64" if="is.running.macos" />
<compilerarg value="-arch" if="is.running.macos" />
<compilerarg value="i386" if="is.running.macos" />
<compilerarg value="-arch" if="is.running.macos" />
<compilerarg value="ppc" if="is.running.macos" />
<compilerarg value="-I/System/Library/Frameworks/JavaVM.framework/Headers" if="is.running.macos" />
<linkerarg value="-o" location="end" if="is.running.macos" />
<linkerarg value="libhwaddressretriever.jnilib" location="end" if="is.running.macos" />
<linkerarg value="-arch" if="is.running.macos" />
<linkerarg value="x86_64" if="is.running.macos" />
<linkerarg value="-arch" if="is.running.macos" />
<linkerarg value="i386" if="is.running.macos" />
<linkerarg value="-arch" if="is.running.macos" />
<linkerarg value="ppc" if="is.running.macos" />
</cc>
</target>
<!-- compile hwaddressretrieverr library for Windows-->
<target name="hwaddressretriever-windows" description="Build hwaddressretriever shared library for Windows" if="is.running.windows"
depends="init-native">
<cc outtype="shared" name="msvc" outfile="${native_install_dir}/hwaddressretriever" objdir="${obj}">
<compilerarg value="/O2" />
<compilerarg value="/MT" location="end" />
<compilerarg value="-I${system.JAVA_HOME}/include" />
<compilerarg value="-I${system.JAVA_HOME}/include/win32" />
<linkerarg value="iphlpapi.lib" location="end" />
<fileset dir="${src}/native/hwaddressretriever" includes="net*.c HardwareAddressRetriever_win.c" />
</cc>
</target>
<!-- compile jvideo4linux2 library -->
<target name="video4linux2" description="Build jvideo4linux2 shared library" if="is.running.linux"
depends="init-native">
@ -654,6 +708,7 @@
<echo message="'ant ffmpeg' to compile ffmpeg shared library" />
<echo message="'ant portaudio' to compile jportaudio shared library" />
<echo message="'ant speex' to compile jspeex shared library" />
<echo message="'ant hwaddressretriever' to compile hwaddressretriever shared library" />
<echo message="'ant video4linux2 (Linux only)' to compile jvideo4linux2 shared library" />
<echo message="'ant galagonotification (Linux only)' to compile galagonotification shared library" />
<echo message="'ant localhostretriever (Windows only)' to compile LocalhostRetriever shared library" />

@ -0,0 +1,30 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
/**
* \file HardwareAddressRetriever.h
* \brief Hardware address retriever.
* \author Sebastien Vincent
* \date 2010
*/
#ifndef HARDWARE_ADDRESS_RETRIEVER_H
#define HARDWARE_ADDRESS_RETRIEVER_H
#include <jni.h>
/**
* \brief Returns the hardware address for the specified interface.
* \param env JNI environment
* \param ifName name of the interface that we want to get the hardware address
* \return byte array representing hardware address or NULL if not found or
* system related errors happen.
*/
jbyteArray getHardwareAddress(JNIEnv* env, jstring ifName);
#endif /* HARDWARE_ADDRESS_RETRIEVER_H */

@ -0,0 +1,124 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
/**
* \file HardwareAddressRetriever_unix.c
* \brief Hardware address retriever (Unix specific code).
* \author Sebastien Vincent
* \date 2010
*/
#if !defined(_WIN32) && !defined(_WIN64)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <net/if.h>
#if defined(__FreeBSD__) || defined(__APPLE__)
#include <ifaddrs.h>
#include <net/if_dl.h>
#include <net/route.h>
#include <net/if_types.h>
#endif
#include "HardwareAddressRetriever.h"
jbyteArray getHardwareAddress(JNIEnv* env, jstring ifName)
{
int sock = -1;
struct ifreq ifr;
jbyteArray hwaddr = NULL;
char* name = NULL;
jbyte* addr = NULL;
int hwlen = 6;
name = (char*)(*env)->GetStringUTFChars(env, ifName, NULL);
if(!name)
{
return NULL;
}
#ifdef __linux__
sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock == -1)
{
(*env)->ReleaseStringUTFChars(env, ifName, name);
return NULL;
}
memset(&ifr, 0x00, sizeof(struct ifreq));
strncpy(ifr.ifr_name, name, IFNAMSIZ - 1);
ifr.ifr_name[IFNAMSIZ - 1] = 0x00;
if(ioctl(sock, SIOCGIFHWADDR, &ifr) != 0)
{
(*env)->ReleaseStringUTFChars(env, ifName, name);
close(sock);
return NULL;
}
close(sock);
addr = (const jbyte*)ifr.ifr_hwaddr.sa_data;
#else /* BSD like */
struct ifaddrs* addrs = NULL;
struct ifaddrs* ifa = NULL;
jbyte buf[hwlen];
if(getifaddrs(&addrs) != -1)
{
for(ifa = addrs ; ifa != NULL ; ifa = ifa->ifa_next)
{
if(ifa->ifa_addr->sa_family == AF_LINK && !strcmp(ifa->ifa_name, name))
{
struct sockaddr_dl* sdl = (struct sockaddr_dl*)ifa->ifa_addr;
if(sdl->sdl_type == IFT_ETHER)
{
memcpy(buf, LLADDR(sdl), hwlen);
addr = buf;
break;
}
}
}
freeifaddrs(addrs);
}
#endif
if(addr)
{
hwaddr = (*env)->NewByteArray(env, hwlen);
if(hwaddr)
{
/* copy the hardware address and return it */
(*env)->SetByteArrayRegion(env, hwaddr, 0, hwlen, addr);
}
}
/* cleanup */
(*env)->ReleaseStringUTFChars(env, ifName, name);
return hwaddr;
}
#endif

@ -0,0 +1,125 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
/**
* \file HardwareAddressRetriever_win.c
* \brief Hardware address retriever (Windows specific code).
* \author Sebastien Vincent
* \date 2010
*/
#if defined(_WIN32) || defined(_WIN64)
/**
* \def WIN32_LEAN_AND_MEAN
* \brief Exclude not commonly used headers from win32 API.
*
* It excludes some unused stuff from windows headers and
* by the way code compiles faster.
*/
#define WIN32_LEAN_AND_MEAN
#include <stdlib.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include "HardwareAddressRetriever.h"
jbyteArray getHardwareAddress(JNIEnv* env, jstring ifName)
{
MIB_IFTABLE* ifTable = NULL;
ULONG size = 15000;
int found = 0;
jbyteArray hwaddr = NULL;
DWORD ret = 0;
DWORD i = 0;
WCHAR* wname = NULL;
MIB_IFROW ifi;
jclass clazz = (*env)->GetObjectClass(env, ifName);
jmethodID method = (*env)->GetMethodID(env, clazz, "compareTo", "(Ljava/lang/String;)I");
if(method == NULL)
{
return NULL;
}
memset(&ifi, 0x00, sizeof(MIB_IFROW));
do
{
ifTable = malloc(size);
if(!ifTable)
{
/* out of memory */
return NULL;
}
ret = GetIfTable(ifTable, &size, 1);
}while(ret == ERROR_INSUFFICIENT_BUFFER);
if(ret != ERROR_SUCCESS)
{
free(ifTable);
return NULL;
}
for(i = 0 ; i < ifTable->dwNumEntries ; i++)
{
jstring tmp = NULL;
ifi = ifTable->table[i];
if(ifi.dwType == IF_TYPE_OTHER)
{
continue;
}
/* jstring created by NewStringUTF will be garbage collected at
* the end of the function
*/
tmp = (*env)->NewStringUTF(env, ifi.bDescr);
if(!tmp)
{
/* printf("error\n"); */
continue;
}
if((*env)->CallIntMethod(env, ifName, method, tmp) == 0)
{
found = 1;
break;
}
}
if(found)
{
DWORD hwlen = ifi.dwPhysAddrLen;
if(hwlen > 0)
{
hwaddr = (*env)->NewByteArray(env, hwlen);
if(hwaddr)
{
/* copy the hardware address and return it */
(*env)->SetByteArrayRegion(env, hwaddr, 0, hwlen, ifi.bPhysAddr);
}
}
}
/* cleanup */
free(ifTable);
return hwaddr;
}
#endif

@ -0,0 +1,35 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
/**
* \file net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever.h
* \brief Hardware address retriever.
* \author Sebastien Vincent
* \date 2010
*/
#include <stdio.h>
#include <stdlib.h>
#include <jni.h>
#include "HardwareAddressRetriever.h"
/**
* \brief Returns the byte array representing hardware address.
* \param env JVM environment
* \param clazz Java class
* \param ifName name of the interface
* \return byte array representing the hardware address or NULL if anything
* goes wrong
*/
JNIEXPORT jbyteArray JNICALL Java_net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever_getHardwareAddress
(JNIEnv* env, jclass clazz, jstring ifName)
{
return getHardwareAddress(env, ifName);
}

@ -0,0 +1,21 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever */
#ifndef _Included_net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever
#define _Included_net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever
* Method: getHardwareAddress
* Signature: (Ljava/lang/String;)[B
*/
JNIEXPORT jbyteArray JNICALL Java_net_java_sip_communicator_impl_netaddr_HardwareAddressRetriever_getHardwareAddress
(JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,33 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.netaddr;
/**
* Class to retrieve hardware address of a specific interface.
*
* We know that starting Java 6, NetworkInterface has getHardwareAddress method
* but as we still support Java 5 we have to do it ourself.
*
* @author Sebastien Vincent
*/
public class HardwareAddressRetriever
{
/* load library */
static
{
System.loadLibrary("hwaddressretriever");
}
/**
* Returns the hardware address of a particular interface.
*
* @param ifName name of the interface
* @return byte array representing the hardware address of the interface or
* null if interface is not found or other system related errors
*/
public static native byte[] getHardwareAddress(String ifName);
}

@ -6,6 +6,7 @@
*/
package net.java.sip.communicator.impl.netaddr;
import java.lang.reflect.*;
import java.beans.*;
import java.io.*;
import java.net.*;
@ -119,7 +120,8 @@ public void stop()
* @return an InetAddress instance representing the local host, and that
* a socket can bind upon or distribute to peers as a contact address.
*/
public synchronized InetAddress getLocalHost(InetAddress intendedDestination)
public synchronized InetAddress getLocalHost(
InetAddress intendedDestination)
{
InetAddress localHost = null;
String osVersion = System.getProperty("os.version");
@ -128,18 +130,20 @@ public synchronized InetAddress getLocalHost(InetAddress intendedDestination)
logger.trace(
"Querying a localhost addr for dst=" + intendedDestination);
/* use native code (JNI) to find source address for a specific destination
* address on Windows XP SP1 and over.
/* use native code (JNI) to find source address for a specific
* destination address on Windows XP SP1 and over.
*
* For other systems, we used method based on DatagramSocket.connect
* which will returns us source address. The reason why we cannot use it
* on Windows is because its socket implementation returns the any address...
* on Windows is because its socket implementation returns the any
* address...
*/
if(OSUtils.IS_WINDOWS &&
!osVersion.startsWith("4") && /* 95/98/Me/NT */
!osVersion.startsWith("5.0")) /* 2000 */
{
byte[] src = Win32LocalhostRetriever.getSourceForDestination(intendedDestination.getAddress());
byte[] src = Win32LocalhostRetriever.getSourceForDestination(
intendedDestination.getAddress());
if(src == null)
{
@ -160,7 +164,8 @@ public synchronized InetAddress getLocalHost(InetAddress intendedDestination)
else
{
//no point in making sure that the localHostFinderSocket is initialized.
//no point in making sure that the localHostFinderSocket is
//initialized.
//better let it through a NullPointerException.
localHostFinderSocket.connect(intendedDestination,
RANDOM_ADDR_DISC_PORT);
@ -235,8 +240,8 @@ public synchronized InetAddress getLocalHost(InetAddress intendedDestination)
if (!(localHost instanceof Inet4Address))
{
// return the first non localhost interface we find.
Enumeration<NetworkInterface> interfaces = NetworkInterface
.getNetworkInterfaces();
Enumeration<NetworkInterface> interfaces =
NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements())
{
@ -278,6 +283,51 @@ public synchronized InetAddress getLocalHost(InetAddress intendedDestination)
return localHost;
}
/**
* Returns the hardware address (i.e. MAC address) of the specified
* interface name.
*
* @param iface the <tt>NetworkInterface</tt>
* @return array of bytes representing the layer 2 address or null if
* interface does not exist
*/
public byte[] getHardwareAddress(NetworkInterface iface)
{
String ifName = null;
byte hwAddress[] = null;
/* try reflection */
try
{
Method method = iface.getClass().
getMethod("getHardwareAddress");
if(method != null)
{
hwAddress = (byte[])method.invoke(iface, new Object[]{});
return hwAddress;
}
}
catch(Exception e)
{
}
/* maybe getHardwareAddress not available on this JVM try
* with our JNI
*/
if(OSUtils.IS_WINDOWS)
{
ifName = iface.getDisplayName();
}
else
{
ifName = iface.getName();
}
hwAddress = HardwareAddressRetriever.getHardwareAddress(ifName);
return hwAddress;
}
/**
* Tries to obtain an for the specified port.
@ -556,8 +606,8 @@ public StunCandidateHarvester discoverStunServer(String domainName,
if(srvrAddress != null)
{
//yay! we seem to have a TURN server, so we'll be using it for both
//TURN and STUN harvesting.
//yay! we seem to have a TURN server, so we'll be using it for
//both TURN and STUN harvesting.
return new TurnCandidateHarvester(
new TransportAddress(srvrAddress, Transport.UDP),
new LongTermCredential(userName, password));

@ -7,7 +7,6 @@
package net.java.sip.communicator.service.netaddr;
import java.net.*;
import java.text.*;
import java.io.*;
import org.ice4j.ice.*;
@ -90,6 +89,15 @@ public InetSocketAddress getPublicAddressFor(
throws IOException,
BindException;
/**
* Returns the hardware address (i.e. MAC address) of the specified
* interface name.
*
* @param iface the <tt>NetworkInterface</tt>
* @return array of bytes representing the layer 2 address
*/
public byte[] getHardwareAddress(NetworkInterface iface);
/**
* Creates a <tt>DatagramSocket</tt> and binds it to on the specified
* <tt>localAddress</tt> and a port in the range specified by the

Loading…
Cancel
Save