This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: RFC: NetworkInterfaces implementation
Hello Tom,
Hello list,
New versions of the java.net.NetworkInterface files. More comments needed.
This files are not for commit right now. Changelog and configure.in.diff is
missing intentionally.
> We need some kind of configure wrapper for this code. Basically, if
> we don't have this capability we ought to just use the default
> implementation of returning an empty vector. (Unless throwing an
> exception is more appropriate -- what do you think?)
I think the current implementation meets to documentation here:
http://java.sun.com/j2se/1.4/docs/api/java/net/NetworkInterface.html
> Should the code throw an exception if ioctl fails?
> I notice that if the ioctl fails then the file descriptor is never
> closed. I think the code should be very defensive here and even make
> sure to catch any exceptions that might be thrown by the various
> library calls so that the cleanups will always be run.
I have reworked that a bit and I think its now JDK (1.4) conform.
> Do the various methods that check and modify networkInterfaces need to
> be synchronized?
What do you mean by this ? synchronized with other methods of
NetworkInterface or with other classes ?
> What is your paperwork status? In order to accept a contribution of
> this size we'll need you to sign the legal papers. If you don't have
> paperwork, tell me and I'll figure out how to get things started.
The paperwork is done. I got the double signed assignment back. I dont know
if there needs to be done more. Brian Youmans, the FSF copyright clerk, can
give you my status if you want.
I dont know how to get a CVS account. Perhaps one day I could need this when
you are tired of sending me patches to you for commit. ;-)
Greetings,
Michael
// natNetworkInterface.cc
/* Copyright (C) 2002 Free Software Foundation
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
#include <config.h>
#ifdef WIN32
#include <windows.h>
#include <winsock.h>
#undef STRICT
#else /* WIN32 */
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/param.h>
#include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#define BSD_COMP /* Get FIONREAD on Solaris2. */
#include <sys/ioctl.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#endif /* WIN32 */
#include <gcj/cni.h>
#include <jvm.h>
#include <java/net/NetworkInterface.h>
#include <java/net/Inet4Address.h>
#include <java/net/Inet6Address.h>
#include <java/net/SocketException.h>
#include <java/util/Vector.h>
#ifdef DISABLE_JAVA_NET
::java::util::Vector*
java::net::NetworkInterface::getRealNetworkInterfaces ()
{
::java::util::Vector* ht = new ::java::util::Vector();
return ht;
}
#else /* DISABLE_JAVA_NET */
::java::util::Vector*
java::net::NetworkInterface::getRealNetworkInterfaces ()
{
int fd;
int num_interfaces = 0;
struct ifconf if_data;
struct ifreq* if_record;
::java::util::Vector* ht = new ::java::util::Vector();
if_data.ifc_len = 0;
if_data.ifc_buf = NULL;
// Open a (random) socket to have a file descriptor for the ioctl calls.
fd = ::socket(PF_INET, SOCK_DGRAM, htons(IPPROTO_IP));
if (fd < 0)
throw new ::java::net::SocketException;
// Get all interfaces. If not enough buffers are available try it
// with a bigger buffer size.
do
{
num_interfaces += 16;
if_data.ifc_len = sizeof(struct ifreq) * num_interfaces;
if_data.ifc_buf =
(char*) _Jv_Realloc(if_data.ifc_buf, if_data.ifc_len);
// Try to get all local interfaces.
if (::ioctl(fd, SIOCGIFCONF, &if_data) < 0)
throw new java::net::SocketException;
}
while (if_data.ifc_len >= (sizeof(struct ifreq) * num_interfaces));
// Get addresses of all interfaces.
if_record = if_data.ifc_req;
for( int n = 0; n < if_data.ifc_len; n += sizeof(struct ifreq) )
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, if_record->ifr_name);
// Try to get the IP-address of the local interface
if (::ioctl(fd, SIOCGIFADDR, &ifr) < 0)
throw new java::net::SocketException;
// FIXME: This assumes IPv4 only
int len = 4;
struct sockaddr_in sa = *((sockaddr_in*) &(ifr.ifr_addr));
jbyteArray baddr = JvNewByteArray (len);
memcpy (elements (baddr), &(sa.sin_addr), len);
jstring if_name = JvNewStringLatin1(if_record->ifr_name);
InetAddress* address = new java::net::InetAddress(
baddr, JvNewStringLatin1(""));
ht->add (new NetworkInterface(if_name, address));
if_record++;
}
_Jv_Free(if_data.ifc_buf);
if (fd >= 0) ::close (fd);
return ht;
}
#endif // DISABLE_JAVA_NET //
// NetworkInterface.java -- A network interface.
/* Copyright (C) 2002 Free Software Foundation
This file is part of libgcj.
This software is copyrighted work licensed under the terms of the
Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
details. */
package java.net;
import java.util.Enumeration;
import java.util.Vector;
/**
* @author Michael Koch <konqueror@gmx.de>
* @since 1.4
*/
public final class NetworkInterface
{
private static Vector networkInterfaces;
private String name;
private Vector inetAddresses;
private NetworkInterface(String name, InetAddress address)
{
this.name = name;
this.inetAddresses = new Vector(1, 1);
this.inetAddresses.add (address);
}
private native static Vector getRealNetworkInterfaces()
throws SocketException;
/**
* Returns the name of the network interface.
*/
public String getName()
{
return name;
}
/**
* Returns all available addresses of the network interface.
* If a @see SecurityManager is available all addresses are checked
* with @see SecurityManager::checkConnect() if they are available.
* Only InetAddresses are returned where the security manager doesn't
* thrown an exception.
*
* @return An enumeration of all addresses.
*/
public Enumeration getInetAddresses()
{
SecurityManager s = System.getSecurityManager();
if (s == null)
return inetAddresses.elements();
Vector tmpInetAddresses = new Vector(1, 1);
for (Enumeration addresses = inetAddresses.elements();
addresses.hasMoreElements(); )
{
InetAddress addr = (InetAddress) addresses.nextElement();
try
{
s.checkConnect(addr.getHostAddress(), 58000);
tmpInetAddresses.add (addr);
}
catch (SecurityException e)
{
}
}
return tmpInetAddresses.elements();
}
/**
* Returns the display name of the interface.
*/
public String getDisplayName()
{
return name;
}
/**
* Returns an network interface by name.
*
* @param name The name of the interface to return
*/
public static NetworkInterface getByName(String name)
throws SocketException
{
if (networkInterfaces == null)
networkInterfaces = getRealNetworkInterfaces();
for (Enumeration e = networkInterfaces.elements();
e.hasMoreElements(); )
{
NetworkInterface tmp = (NetworkInterface) e.nextElement();
if (name.equals(tmp.getName()))
return tmp;
}
throw new SocketException("no network interface with this name exists");
}
/**
* Return a network interface by its address.
*
* @param addr The address of the interface to return.
*/
public static NetworkInterface getByInetAddress(InetAddress addr)
throws SocketException
{
if (networkInterfaces == null)
networkInterfaces = getRealNetworkInterfaces();
for (Enumeration interfaces = networkInterfaces.elements();
interfaces.hasMoreElements();)
{
NetworkInterface tmp = (NetworkInterface) interfaces.nextElement();
for (Enumeration addresses = tmp.inetAddresses.elements();
addresses.hasMoreElements();)
{
if (addr.equals((InetAddress) addresses.nextElement()))
return tmp;
}
}
throw new SocketException(
"no network intefaces is bound to such an IP address");
}
/**
* Return an Enumeration of all available network interfaces.
*/
public static Enumeration getNetworkInterfaces()
throws SocketException
{
if (networkInterfaces == null)
networkInterfaces = getRealNetworkInterfaces();
Enumeration tmp = networkInterfaces.elements();
if (tmp.hasMoreElements())
return tmp;
return null;
}
/**
* Checks if the current instance is equal to obj.
*/
public boolean equals(Object obj)
{
if (!(obj instanceof NetworkInterface))
return false;
NetworkInterface tmp = (NetworkInterface) obj;
return name.equals(tmp.name) && inetAddresses.equals(tmp.inetAddresses);
}
/**
* Returns the hashcode of the current instance.
*/
public int hashCode()
{
// FIXME: hash correctly
return name.hashCode() + inetAddresses.hashCode();
}
/**
* Returns a string representation of the interface.
*/
public String toString()
{
// FIXME: check if this is correct
String result;
result = "name: "+getDisplayName()+" ("+getName()+") addresses:\n";
for (Enumeration e = inetAddresses.elements(); e.hasMoreElements(); )
{
InetAddress address = (InetAddress) e.nextElement();
result += address.toString() + "\n";
}
return result;
}
} // class NetworkInterface