This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]