1 28 package org.jruby.ext.socket; 29 30 import java.io.EOFException ; 31 import java.io.IOException ; 32 import java.nio.channels.Channel ; 33 import java.nio.channels.SocketChannel ; 34 import java.nio.channels.ServerSocketChannel ; 35 import java.net.SocketAddress ; 36 import java.net.InetSocketAddress ; 37 import org.jruby.Ruby; 38 import org.jruby.RubyClass; 39 import org.jruby.RubyNumeric; 40 import org.jruby.RubyIO; 41 import org.jruby.RubyString; 42 import org.jruby.runtime.CallbackFactory; 43 import org.jruby.runtime.ObjectAllocator; 44 import org.jruby.runtime.builtin.IRubyObject; 45 import org.jruby.util.IOHandlerNio; 46 import org.jruby.util.IOHandler; 47 48 51 public class RubyBasicSocket extends RubyIO { 52 private static ObjectAllocator BASICSOCKET_ALLOCATOR = new ObjectAllocator() { 53 public IRubyObject allocate(Ruby runtime, RubyClass klass) { 54 return new RubyBasicSocket(runtime, klass); 55 } 56 }; 57 58 static void createBasicSocket(Ruby runtime) { 59 RubyClass rb_cBasicSocket = runtime.defineClass("BasicSocket", runtime.getClass("IO"), BASICSOCKET_ALLOCATOR); 60 61 CallbackFactory cfact = runtime.callbackFactory(RubyBasicSocket.class); 62 rb_cBasicSocket.defineFastMethod("send", cfact.getFastOptMethod("write_send")); 63 rb_cBasicSocket.defineFastMethod("recv", cfact.getFastOptMethod("recv")); 64 rb_cBasicSocket.defineFastMethod("shutdown", cfact.getFastOptMethod("shutdown")); 65 rb_cBasicSocket.defineFastMethod("__getsockname", cfact.getFastMethod("getsockname")); 66 rb_cBasicSocket.defineFastMethod("__getpeername", cfact.getFastMethod("getpeername")); 67 rb_cBasicSocket.defineFastMethod("getsockname", cfact.getFastMethod("getsockname")); 68 rb_cBasicSocket.defineFastMethod("getpeername", cfact.getFastMethod("getpeername")); 69 rb_cBasicSocket.getMetaClass().defineFastMethod("do_not_reverse_lookup", cfact.getFastSingletonMethod("do_not_reverse_lookup")); 70 rb_cBasicSocket.getMetaClass().defineFastMethod("do_not_reverse_lookup=", cfact.getFastSingletonMethod("set_do_not_reverse_lookup", IRubyObject.class)); 71 } 72 73 protected Channel socketChannel; 74 75 public RubyBasicSocket(Ruby runtime, RubyClass type) { 76 super(runtime, type); 77 } 78 79 protected void setChannel(Channel c) { 80 this.socketChannel = c; 81 try { 82 handler = new IOHandlerNio(getRuntime(), socketChannel); 83 handler.setIsSync(true); 84 } catch (IOException e) { 85 throw getRuntime().newIOError(e.getMessage()); 86 } 87 registerIOHandler(handler); 88 modes = handler.getModes(); 89 } 90 91 public IRubyObject write_send(IRubyObject[] args) { 92 return syswrite(args[0]); 93 } 94 95 public IRubyObject recv(IRubyObject[] args) { 96 try { 97 return RubyString.newString(getRuntime(), ((IOHandlerNio) handler).recv(RubyNumeric.fix2int(args[0]))); 98 } catch (IOHandler.BadDescriptorException e) { 99 throw getRuntime().newErrnoEBADFError(); 100 } catch (EOFException e) { 101 return getRuntime().getNil(); 103 } catch (IOException e) { 104 if ("Socket not open".equals(e.getMessage())) { 108 throw getRuntime().newIOError(e.getMessage()); 109 } 110 throw getRuntime().newSystemCallError(e.getMessage()); 111 } 112 } 113 114 protected InetSocketAddress getLocalSocket() { 115 if (socketChannel instanceof SocketChannel ) { 116 return (InetSocketAddress )((SocketChannel )socketChannel).socket().getLocalSocketAddress(); 117 } else if (socketChannel instanceof ServerSocketChannel ) { 118 return (InetSocketAddress )((ServerSocketChannel ) socketChannel).socket().getLocalSocketAddress(); 119 } else { 120 return null; 121 } 122 } 123 124 protected InetSocketAddress getRemoteSocket() { 125 if(socketChannel instanceof SocketChannel ) { 126 return (InetSocketAddress )((SocketChannel )socketChannel).socket().getRemoteSocketAddress(); 127 } else { 128 return null; 129 } 130 } 131 132 public IRubyObject getsockname() { 133 SocketAddress sock = getLocalSocket(); 134 if(null == sock) { 135 throw getRuntime().newIOError("Not Supported"); 136 } 137 return getRuntime().newString(sock.toString()); 138 } 139 140 public IRubyObject getpeername() { 141 SocketAddress sock = getRemoteSocket(); 142 if(null == sock) { 143 throw getRuntime().newIOError("Not Supported"); 144 } 145 return getRuntime().newString(sock.toString()); 146 } 147 148 public IRubyObject shutdown(IRubyObject[] args) { 149 if (getRuntime().getSafeLevel() >= 4 && tainted().isFalse()) { 150 throw getRuntime().newSecurityError("Insecure: can't shutdown socket"); 151 } 152 153 int how = 2; 154 if (args.length > 0) { 155 how = RubyNumeric.fix2int(args[0]); 156 } 157 if (how < 0 || 2 < how) { 158 throw getRuntime().newArgumentError("`how' should be either 0, 1, 2"); 159 } 160 if (how != 2) { 161 throw getRuntime().newNotImplementedError("Shutdown currently only works with how=2"); 162 } 163 return close(); 164 } 165 166 public static IRubyObject do_not_reverse_lookup(IRubyObject recv) { 167 return recv.getRuntime().isDoNotReverseLookupEnabled() ? recv.getRuntime().getTrue() : recv.getRuntime().getFalse(); 168 } 169 170 public static IRubyObject set_do_not_reverse_lookup(IRubyObject recv, IRubyObject flag) { 171 recv.getRuntime().setDoNotReverseLookupEnabled(flag.isTrue()); 172 return recv.getRuntime().isDoNotReverseLookupEnabled() ? recv.getRuntime().getTrue() : recv.getRuntime().getFalse(); 173 } 174 } | Popular Tags |