1 28 package org.jruby.ext.socket; 29 30 import java.io.IOException ; 31 import java.net.InetAddress ; 32 import java.net.UnknownHostException ; 33 import java.util.ArrayList ; 34 import java.util.List ; 35 36 import org.jruby.Ruby; 37 import org.jruby.RubyArray; 38 import org.jruby.RubyClass; 39 import org.jruby.RubyModule; 40 import org.jruby.RubyNumeric; 41 import org.jruby.exceptions.RaiseException; 42 import org.jruby.runtime.CallbackFactory; 43 import org.jruby.runtime.ObjectAllocator; 44 import org.jruby.runtime.builtin.IRubyObject; 45 import org.jruby.runtime.load.Library; 46 import org.jruby.util.ByteList; 47 48 51 public class RubySocket extends RubyBasicSocket { 52 public static class Service implements Library { 53 public void load(final Ruby runtime) throws IOException { 54 runtime.defineClass("SocketError",runtime.getClass("StandardError"), runtime.getClass("StandardError").getAllocator()); 55 RubyBasicSocket.createBasicSocket(runtime); 56 RubySocket.createSocket(runtime); 57 RubyIPSocket.createIPSocket(runtime); 58 RubyTCPSocket.createTCPSocket(runtime); 59 RubyTCPServer.createTCPServer(runtime); 60 } 61 } 62 63 private static ObjectAllocator SOCKET_ALLOCATOR = new ObjectAllocator() { 64 public IRubyObject allocate(Ruby runtime, RubyClass klass) { 65 return new RubySocket(runtime, klass); 66 } 67 }; 68 69 static void createSocket(Ruby runtime) { 70 RubyClass rb_cSocket = runtime.defineClass("Socket", runtime.getClass("BasicSocket"), SOCKET_ALLOCATOR); 71 CallbackFactory cfact = runtime.callbackFactory(RubySocket.class); 72 73 RubyModule rb_mConstants = rb_cSocket.defineModuleUnder("Constants"); 74 76 rb_mConstants.setConstant("SOCK_STREAM", runtime.newFixnum(1)); 77 rb_mConstants.setConstant("SOCK_DGRAM", runtime.newFixnum(2)); 78 rb_mConstants.setConstant("PF_UNSPEC", runtime.newFixnum(0)); 79 rb_mConstants.setConstant("AF_UNSPEC", runtime.newFixnum(0)); 80 rb_mConstants.setConstant("PF_INET", runtime.newFixnum(2)); 81 rb_mConstants.setConstant("AF_INET", runtime.newFixnum(2)); 82 rb_mConstants.setConstant("MSG_OOB", runtime.newFixnum(0x01)); 84 rb_mConstants.setConstant("SOL_SOCKET", runtime.newFixnum(1)); 85 rb_mConstants.setConstant("SOL_IP", runtime.newFixnum(0)); 86 rb_mConstants.setConstant("SOL_TCP", runtime.newFixnum(6)); 87 rb_mConstants.setConstant("SOL_UDP", runtime.newFixnum(17)); 88 rb_mConstants.setConstant("IPPROTO_IP", runtime.newFixnum(0)); 89 rb_mConstants.setConstant("IPPROTO_ICMP", runtime.newFixnum(1)); 90 rb_mConstants.setConstant("IPPROTO_TCP", runtime.newFixnum(6)); 91 rb_mConstants.setConstant("IPPROTO_UDP", runtime.newFixnum(17)); 92 rb_mConstants.setConstant("INADDR_ANY", runtime.newFixnum(0x00000000)); 94 rb_mConstants.setConstant("INADDR_BROADCAST", runtime.newFixnum(0xffffffff)); 95 rb_mConstants.setConstant("INADDR_LOOPBACK", runtime.newFixnum(0x7f000001)); 96 rb_mConstants.setConstant("INADDR_UNSPEC_GROUP", runtime.newFixnum(0xe0000000)); 97 rb_mConstants.setConstant("INADDR_ALLHOSTS_GROUP", runtime.newFixnum(0xe0000001)); 98 rb_mConstants.setConstant("INADDR_MAX_LOCAL_GROUP", runtime.newFixnum(0xe00000ff)); 99 rb_mConstants.setConstant("INADDR_NONE", runtime.newFixnum(0xffffffff)); 100 rb_mConstants.setConstant("SO_REUSEADDR", runtime.newFixnum(2)); 101 rb_mConstants.setConstant("SHUT_RD", runtime.newFixnum(0)); 102 rb_mConstants.setConstant("SHUT_WR", runtime.newFixnum(1)); 103 rb_mConstants.setConstant("SHUT_RDWR", runtime.newFixnum(2)); 104 105 rb_mConstants.setConstant("AI_PASSIVE", runtime.newFixnum(1)); 107 108 rb_mConstants.setConstant("SO_KEEPALIVE", runtime.newFixnum(9)); 110 111 rb_mConstants.setConstant("TCP_NODELAY", runtime.newFixnum(1)); 113 114 rb_cSocket.includeModule(rb_mConstants); 115 116 rb_cSocket.getMetaClass().defineFastMethod("gethostname", cfact.getFastSingletonMethod("gethostname")); 117 rb_cSocket.getMetaClass().defineFastMethod("gethostbyaddr", cfact.getFastOptSingletonMethod("gethostbyaddr")); 118 rb_cSocket.getMetaClass().defineFastMethod("gethostbyname", cfact.getFastSingletonMethod("gethostbyname", IRubyObject.class)); 119 rb_cSocket.getMetaClass().defineFastMethod("getaddrinfo", cfact.getFastOptSingletonMethod("getaddrinfo")); 120 rb_cSocket.getMetaClass().defineFastMethod("getnameinfo", cfact.getFastOptSingletonMethod("getnameinfo")); 121 } 122 123 public RubySocket(Ruby runtime, RubyClass type) { 124 super(runtime, type); 125 } 126 127 private static RuntimeException sockerr(IRubyObject recv, String msg) { 128 return new RaiseException(recv.getRuntime(), recv.getRuntime().getClass("SocketError"), null, true); 129 } 130 131 public static IRubyObject gethostname(IRubyObject recv) { 132 try { 133 return recv.getRuntime().newString(InetAddress.getLocalHost().getHostName()); 134 } catch(UnknownHostException e) { 135 throw sockerr(recv, "gethostname: name or service not known"); 136 } 137 } 138 139 private static InetAddress intoAddress(IRubyObject recv, String s) { 140 try { 141 byte[] bs = ByteList.plain(s); 142 return InetAddress.getByAddress(bs); 143 } catch(Exception e) { 144 throw sockerr(recv, "strtoaddr: " + e.toString()); 145 } 146 } 147 148 private static String intoString(IRubyObject recv, InetAddress as) { 149 try { 150 return new String (ByteList.plain(as.getAddress())); 151 } catch(Exception e) { 152 throw sockerr(recv, "addrtostr: " + e.toString()); 153 } 154 } 155 156 public static IRubyObject gethostbyaddr(IRubyObject recv, IRubyObject[] args) { 157 recv.checkArgumentCount(args,1,2); 158 Ruby runtime = recv.getRuntime(); 159 IRubyObject[] ret = new IRubyObject[4]; 160 ret[0] = runtime.newString(intoAddress(recv,args[0].convertToString().toString()).getCanonicalHostName()); 161 ret[1] = runtime.newArray(); 162 ret[2] = runtime.newFixnum(2); ret[3] = args[0]; 164 return runtime.newArrayNoCopy(ret); 165 } 166 167 public static IRubyObject gethostbyname(IRubyObject recv, IRubyObject hostname) { 168 try { 169 InetAddress addr = InetAddress.getByName(hostname.convertToString().toString()); 170 Ruby runtime = recv.getRuntime(); 171 IRubyObject[] ret = new IRubyObject[4]; 172 ret[0] = runtime.newString(addr.getCanonicalHostName()); 173 ret[1] = runtime.newArray(); 174 ret[2] = runtime.newFixnum(2); ret[3] = runtime.newString(intoString(recv,addr)); 176 return runtime.newArrayNoCopy(ret); 177 } catch(UnknownHostException e) { 178 throw sockerr(recv, "gethostbyname: name or service not known"); 179 } 180 } 181 182 public static IRubyObject getaddrinfo(IRubyObject recv, IRubyObject[] args) { 184 args = recv.scanArgs(args,2,4); 185 try { 186 Ruby r = recv.getRuntime(); 187 IRubyObject host = args[0]; 188 IRubyObject port = args[1]; 189 IRubyObject socktype = args[3]; 191 boolean sock_stream = true; 194 boolean sock_dgram = true; 195 if(!socktype.isNil()) { 196 int val = RubyNumeric.fix2int(socktype); 197 if(val == 1) { 198 sock_dgram = false; 199 } else if(val == 2) { 200 sock_stream = false; 201 } 202 } 203 InetAddress [] addrs = InetAddress.getAllByName(host.isNil() ? null : host.convertToString().toString()); 204 List l = new ArrayList (); 205 for(int i=0;i<addrs.length;i++) { 206 IRubyObject[] c; 207 if(sock_stream) { 208 c = new IRubyObject[7]; 209 c[0] = r.newString("AF_INET"); 210 c[1] = port; 211 c[2] = r.newString(addrs[i].getCanonicalHostName()); 212 c[3] = r.newString(addrs[i].getHostAddress()); 213 c[4] = r.newFixnum(2); c[5] = r.newFixnum(1); c[6] = r.newFixnum(6); l.add(r.newArrayNoCopy(c)); 217 } 218 if(sock_dgram) { 219 c = new IRubyObject[7]; 220 c[0] = r.newString("AF_INET"); 221 c[1] = port; 222 c[2] = r.newString(addrs[i].getCanonicalHostName()); 223 c[3] = r.newString(addrs[i].getHostAddress()); 224 c[4] = r.newFixnum(2); c[5] = r.newFixnum(2); c[6] = r.newFixnum(17); l.add(r.newArrayNoCopy(c)); 228 } 229 } 230 return r.newArray(l); 231 } catch(UnknownHostException e) { 232 throw sockerr(recv, "getaddrinfo: name or service not known"); 233 } 234 } 235 236 public static IRubyObject getnameinfo(IRubyObject recv, IRubyObject[] args) { 237 args = recv.scanArgs(args,1,1); 239 if (args[0] instanceof RubyArray) { 240 try { 241 List l = ((RubyArray)args[0]).getList(); 242 IRubyObject[] ret = new IRubyObject[2]; 243 ret[0] = recv.getRuntime().newString(InetAddress.getByName(l.get(2).toString()).getCanonicalHostName()); 244 ret[1] = (IRubyObject)l.get(1); 245 246 return recv.getRuntime().newArrayNoCopy(ret); 247 } catch(UnknownHostException e) { 248 throw sockerr(recv, "getnameinfo: name or service not known"); 249 } 250 } 251 252 throw sockerr(recv, "getnameinfo: string version not supported yet"); 253 } 254 } | Popular Tags |