A Raw Socket Class

Listing 1. A few native methods unlock the basics of raw sockets.

package org.savarese.rocksaw.net;

import java.net.InetAddress;
import java.io.IOException;

public class RawSocket {

  public static final int PF_INET  = 2;
  public static final int PF_INET6 = 10 ;

  static {
    System.loadLibrary("rocksaw");
  }

  private static final int __UNDEFINED = -1;

  private int __socket;
  private int __family;

  public RawSocket() {
    __socket = __UNDEFINED;
    __family = __UNDEFINED;
  }

  public boolean isOpen() {
    return (__socket > 0);
  }

  private native void __getErrorMessage(
    StringBuffer buffer);

  private void __throwIOException() throws 
    IOException {
    StringBuffer buf = new StringBuffer();
    __getErrorMessage(buf);
    throw new IOException(buf.toString());
  }

  private native int
    __socket(int protocolFamily, int protocol);

  public native static final int getProtocolByName(
    String name);

  public void open(int protocolFamily, int protocol)
    throws IllegalStateException, IOException
  {
    if(isOpen())
      throw new IllegalStateException();
    __socket = __socket(protocolFamily, protocol);

    if(__socket < 0) {
      __socket = UNDEFINED;
      __throwIOException();
    }

    __family = protocolFamily;
  }

  private native int __close(int socket);

  public void close() throws IOException {
    int result = __close(__socket);
    __socket = __UNDEFINED;
    __family = __UNDEFINED;

    if(result != 0)
      __throwIOException();
  }

  private native int
    __recvfrom(int socket, byte[] data, int offset,
              int length, int family, byte[] address);

  public int read(InetAddress address, byte[] data, 
    int offset, int length)
    throws IllegalArgumentException, IOException 
  {
    if(offset < 0 || offset >= 
      data.length || length < 0 ||
      length > data.length - offset)
      throw new IllegalArgumentException(
        "Invalid offset or length.");

    int result =
      __recvfrom(__socket, data, offset, length, 
      __family, address.getAddress());

    if(result < 0)
      __throwIOException();

    return result;
  }

  public int read(InetAddress address, byte[] data)
    throws IOException
  {
    return read(address, data, 0, data.length);
  }

  private native int
    __sendto(int socket, byte[] data, int offset,
              int length, int family, byte[] address);

  public int write(InetAddress address, byte[] data,
                   int offset, int length)
    throws IllegalArgumentException, IOException 
  {
    if(offset < 0 || offset >= data.length || length < 
      0 || length > data.length - offset)
      throw new IllegalArgumentException(
        "Invalid offset or length.");

    int result =
      __sendto(__socket, data, offset, length,
      __family, address.getAddress());

    if(result < 0)
      __throwIOException();

    return result;
  }

  public int write(InetAddress address, byte[] data)
    throws IOException
  {
    return write(address, data, 0, data.length);
  }
}