diff -ruN --exclude=CVS jruby-vanilla/src/builtin/socket.rb jruby/src/builtin/socket.rb
--- jruby-vanilla/src/builtin/socket.rb	2006-04-27 10:26:26.000000000 -0700
+++ jruby/src/builtin/socket.rb	2006-04-27 19:16:09.000000000 -0700
@@ -12,6 +12,7 @@
 # * rights and limitations under the License.
 # *
 # * Copyright (C) 2005 David Corbin <dcorbin@users.sourceforge.net>
+# * Copyright (C) 2006 Evan Buswell <evan@heron.sytes.net>
 # * 
 # * Alternatively, the contents of this file may be used under the terms of
 # * either of the GNU General Public License Version 2 or later (the "GPL"),
@@ -27,38 +28,118 @@
 # ***** END LICENSE BLOCK *****/
 require "java"
 
+class SocketError < StandardError; end
+
+class BasicSocket
+  def getsockname
+    JavaUtilities.wrap(__getsockname)
+  end
+  def getpeername
+    JavaUtilities.wrap(__getpeername)
+  end
+end
+
 class Socket < BasicSocket
-  include_class 'java.net.InetAddress'
-  include_class 'java.net.UnknownHostException'
+  include_class('java.net.InetAddress')
+  include_class('java.net.InetSocketAddress')
+  include_class('java.net.UnknownHostException')
+  module Constants
+    # we don't have to define any that we don't support; see socket.c
+    SOCK_STREAM, SOCK_DGRAM = 1, 2
+    PF_UNSPEC = 0
+    AF_UNSPEC = PF_UNSPEC
+    PF_INET = 2
+    AF_INET = PF_INET
+  end
+  include Constants
 
   def self.gethostname
-    begin
-      # FIXME: Static methods should allow java short-hand
-	  InetAddress.getLocalHost.hostName
-	rescue UnknownHostException => e
-	  throw SystemError.new("gethostname")
-	end
+    # FIXME: Static methods should allow java short-hand
+    InetAddress.getLocalHost.hostName
+  rescue UnknownHostException => e
+    raise SocketError.new("getaddrinfo: Name or service not known")
+  end
+
+  def self.gethostbyaddr(addr, type=AF_INET)
+    return [ addr.getAddress.getCanonicalHostName, [], AF_INET, addr ]
+  rescue UnknownHostException => e
+    raise SocketError.new("getaddrinfo: Name or service not known")
+  end
+
+  def self.gethostbyname(hostname)
+    addr = InetAddress.getByName(hostname)
+    return [ addr.getCanonicalHostName, [], AF_INET, InetSocketAddress.new(addr, 0) ]
+  rescue UnknownHostException => e
+    throw SocketError.new("getaddrinfo: Name or service not known")
+  end
+
+  def self.getaddrinfo(host, port, family = nil, socktype = nil, protocol = nil, flags = nil)
+    addrs = InetAddress.getAllByName(host)
+    return addrs.inject([]) do |array, addr|
+      # protocol number 6 is TCP
+      array << [ "AF_INET", port, addr.getHostName, addr.getHostAddress, PF_INET, SOCK_STREAM, 6 ]
+    end
+  rescue UnknownHostException => e
+    raise SocketError.new("getaddrinfo: Name or service not known")
+  end
+  
+  def self.getnameinfo(addr, flags = nil)
+    # since strings act a lot like arrays, we can't easily distinguish them by behaviour
+    if(addr.kind_of? Array)
+      return [ InetAddress.getByName(addr[2]).getCanonicalHostName, addr[1] ]
+    else
+      return [ addr.getAddress.getCanonicalHostName, addr.getPort ]
+    end
+  rescue UnknownHostException => e
+    raise SocketError.new("getaddrinfo: Name or service not known")
   end
 end
 
 class IPSocket < BasicSocket
+  include_class('java.net.InetAddress')
+  include_class('java.net.InetSocketAddress')
+  include_class('java.net.UnknownHostException')
+  def addr
+    addr = getsockname
+    return [ "AF_INET",
+      addr.getPort,
+      (BasicSocket.do_not_reverse_lookup ? addr.getAddress.getHostAddress : addr.getHostName),
+      addr.getAddress.getHostAddress ]
+  end
+  def peeraddr()
+    addr = getpeername
+    return [ "AF_INET",
+      addr.getPort,
+      (BasicSocket.do_not_reverse_lookup ? addr.getAddress.getHostAddress : addr.getHostName),
+      addr.getAddress.getHostAddress ]
+  end
+  def self.getaddress(hostname)
+    return InetAddress.getByName(hostname).getHostAddress
+  rescue UnknownHostException => e
+    throw SocketError.new("getaddrinfo: Name or service not known")
+  end
 end
 
 class TCPSocket < IPSocket
-  include_class('org.jruby.util.IOHandlerUnseekable') 
-  include_class('org.jruby.RubyIO') 
+  include Socket::Constants
+  include_class('java.net.InetAddress')
   include_class('java.net.ConnectException') 
   include_class('java.net.Socket') {|p,c| 'JavaSocket'}
+  include_class('java.net.UnknownHostException')
   
   def initialize(arg1, port) 
     begin
       if port
-        @javaSocket = JavaSocket.new(arg1, port)
+        begin
+          javaSocket = JavaSocket.new(arg1, port)
+        rescue UnknownHostException
+          raise SocketError.new("getaddrinfo: Name or service not known")
+        end
       else 
-        @javaSocket = arg1
+        javaSocket = arg1
       end
         
-      super @javaSocket.getInputStream, @javaSocket.getOutputStream
+      super javaSocket
     rescue ConnectException => e
       raise Errno::ECONNREFUSED.new
     end
@@ -77,16 +158,25 @@
       sock
     end
   end
+  def self.gethostbyname(hostname)
+    addr = InetAddress.getByName(hostname)
+    return [ addr.getCanonicalHostName, [], AF_INET, addr.getHostAddress ]
+  rescue UnknownHostException => e
+    throw SocketError.new("getaddrinfo: Name or service not known")
+  end
 end
 
 class TCPServer < TCPSocket
   include_class('java.net.ServerSocket')
   include_class('java.net.InetAddress')
+  include_class('java.net.UnknownHostException')
 
   def initialize(hostname, port) 
       addr = nil
       addr = InetAddress.getByName hostname if hostname
       @javaServerSocket = ServerSocket.new(port, 10, addr)
+  rescue UnknownHostException => e
+    raise SocketError.new("getaddrinfo: Name or service not known")
   end
   
   def self.open(*args)
diff -ruN --exclude=CVS jruby-vanilla/src/org/jruby/RubyBasicSocket.java jruby/src/org/jruby/RubyBasicSocket.java
--- jruby-vanilla/src/org/jruby/RubyBasicSocket.java	2006-04-27 10:26:26.000000000 -0700
+++ jruby/src/org/jruby/RubyBasicSocket.java	2006-04-27 19:16:35.000000000 -0700
@@ -12,7 +12,7 @@
  * rights and limitations under the License.
  *
  * Copyright (C) 2005 David Corbin <dcorbin@users.sourceforge.net>
- * Copyright (C) 2006 Evan <evan@heron.sytes.net>
+ * Copyright (C) 2006 Evan Buswell <evan@heron.sytes.net>
  * 
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
@@ -32,6 +32,7 @@
 import java.io.OutputStream;
 import java.io.EOFException;
 import java.io.IOException;
+import java.net.Socket;
 
 import org.jruby.javasupport.JavaObject;
 import org.jruby.runtime.builtin.IRubyObject;
@@ -39,19 +40,18 @@
 import org.jruby.util.IOHandler;
 
 public class RubyBasicSocket extends RubyIO {
-
+    public static boolean do_not_reverse_lookup = false;
+    private Socket socket;
+    
     public RubyBasicSocket(IRuby runtime, RubyClass type) {
         super(runtime, type);
     }
     
-    public IRubyObject initialize(IRubyObject[] args) {
-        IRubyObject input 	= args[0];
-        IRubyObject output 	= args[1];
+    public IRubyObject initialize(IRubyObject arg) {
+	socket = extractSocket(arg);
         
-        InputStream inputStream = (InputStream) extractStream(input);
-        OutputStream outputStream = (OutputStream) extractStream(output);
         try {
-            handler = new IOHandlerSocket(getRuntime(), inputStream, outputStream);
+            handler = new IOHandlerSocket(getRuntime(), socket.getInputStream(), socket.getOutputStream());
     	} catch (IOException e) {
             throw getRuntime().newIOError(e.getMessage());
         }
@@ -61,9 +61,9 @@
         return this;
     }
     
-    private Object extractStream(IRubyObject proxyObject) {
+    private Socket extractSocket(IRubyObject proxyObject) {
         IRubyObject javaObject = proxyObject.getInstanceVariable("@java_object");
-        return ((JavaObject)javaObject).getValue();
+        return (Socket) ((JavaObject) javaObject).getValue();
     }
 
     public IRubyObject write_send(IRubyObject[] args) {
@@ -88,4 +88,29 @@
     	    throw getRuntime().newSystemCallError(e.getMessage());
     	}
     }
+
+    public IRubyObject getsockname() {
+	return JavaObject.wrap(getRuntime(), socket.getLocalSocketAddress());
+    }
+
+    public IRubyObject getpeername() {
+	return JavaObject.wrap(getRuntime(), socket.getRemoteSocketAddress());
+    }
+
+    public IRubyObject shutdown(IRubyObject[] args) {
+	if(getRuntime().getSafeLevel() >= 4 && tainted().isFalse()) {
+	    throw getRuntime().newSecurityError("Insecure: can't shutdown socket");
+	}
+	int how = 2;
+	if(args.length > 0) {
+	    how = RubyNumeric.fix2int(args[0]);
+	}
+	if(how < 0 || 2 < how) {
+	    throw getRuntime().newArgumentError("`how' should be either 0, 1, 2");
+	}
+	if(how != 2) {
+	    throw getRuntime().newNotImplementedError("Shutdown currently only works with how=2");
+	}
+	return close();
+    }
 }
diff -ruN --exclude=CVS jruby-vanilla/src/org/jruby/runtime/builtin/meta/BasicSocketMetaClass.java jruby/src/org/jruby/runtime/builtin/meta/BasicSocketMetaClass.java
--- jruby-vanilla/src/org/jruby/runtime/builtin/meta/BasicSocketMetaClass.java	2006-04-27 10:26:26.000000000 -0700
+++ jruby/src/org/jruby/runtime/builtin/meta/BasicSocketMetaClass.java	2006-04-27 19:17:15.000000000 -0700
@@ -12,7 +12,7 @@
  * rights and limitations under the License.
  *
  * Copyright (C) 2005 David Corbin <dcorbin@users.sourceforge.net>
- * Copyright (C) 2006 Evan <evan@heron.sytes.net>
+ * Copyright (C) 2006 Evan Buswell <evan@heron.sytes.net>
  * Copyright (C) 2006 Thomas E Enebo <enebo@acm.org>
  * 
  * Alternatively, the contents of this file may be used under the terms of
@@ -33,6 +33,7 @@
 import org.jruby.RubyBasicSocket;
 import org.jruby.RubyClass;
 import org.jruby.RubyModule;
+import org.jruby.RubyBoolean;
 import org.jruby.runtime.builtin.IRubyObject;
 import org.jruby.runtime.Arity;
 import org.jruby.util.collections.SinglyLinkedList;
@@ -53,11 +54,25 @@
 
     protected class BasicSocketMeta extends Meta {
     	protected void initializeClass() {
-            defineMethod("initialize", Arity.optional());
+            defineMethod("initialize", Arity.singleArgument());
             defineMethod("send", Arity.optional(), "write_send");
-            defineMethod("recv", Arity.optional(), "recv");
+            defineMethod("recv", Arity.optional());
+            defineMethod("shutdown", Arity.optional());
+	    defineMethod("__getsockname", Arity.noArguments(), "getsockname");
+	    defineMethod("__getpeername", Arity.noArguments(), "getpeername");
+	    defineSingletonMethod("do_not_reverse_lookup", Arity.noArguments());
+	    defineSingletonMethod("do_not_reverse_lookup=", Arity.singleArgument(), "set_do_not_reverse_lookup");
     	}
     };
+
+    public IRubyObject do_not_reverse_lookup() {
+	return getRuntime().newBoolean(RubyBasicSocket.do_not_reverse_lookup);
+    }
+    
+    public IRubyObject set_do_not_reverse_lookup(IRubyObject flag) {
+	RubyBasicSocket.do_not_reverse_lookup = ((RubyBoolean) flag).isTrue();
+	return getRuntime().newBoolean(RubyBasicSocket.do_not_reverse_lookup);
+    }
     
     protected Meta getMeta() {
     	return new BasicSocketMeta();
