KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > ext > socket > RubySocket


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2007 Ola Bini <ola@ologix.com>
15  *
16  * Alternatively, the contents of this file may be used under the terms of
17  * either of the GNU General Public License Version 2 or later (the "GPL"),
18  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
19  * in which case the provisions of the GPL or the LGPL are applicable instead
20  * of those above. If you wish to allow use of your version of this file only
21  * under the terms of either the GPL or the LGPL, and not to allow others to
22  * use your version of this file under the terms of the CPL, indicate your
23  * decision by deleting the provisions above and replace them with the notice
24  * and other provisions required by the GPL or the LGPL. If you do not delete
25  * the provisions above, a recipient may use your version of this file under
26  * the terms of any one of the CPL, the GPL or the LGPL.
27  ***** END LICENSE BLOCK *****/

28 package org.jruby.ext.socket;
29
30 import java.io.IOException JavaDoc;
31 import java.net.InetAddress JavaDoc;
32 import java.net.UnknownHostException JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.List JavaDoc;
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 /**
49  * @author <a HREF="mailto:ola.bini@ki.se">Ola Bini</a>
50  */

51 public class RubySocket extends RubyBasicSocket {
52     public static class Service implements Library {
53         public void load(final Ruby runtime) throws IOException JavaDoc {
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         // we don't have to define any that we don't support; see socket.c
75

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         // mandatory constants we haven't implemented
83
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         // IPPROTO_RAW = 255
93
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         // constants webrick crashes without
106
rb_mConstants.setConstant("AI_PASSIVE", runtime.newFixnum(1));
107
108         // constants Rails > 1.1.4 ActiveRecord's default mysql adapter dies without during scaffold generation
109
rb_mConstants.setConstant("SO_KEEPALIVE", runtime.newFixnum(9));
110     
111         // drb needs defined
112
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 JavaDoc sockerr(IRubyObject recv, String JavaDoc 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 JavaDoc e) {
135             throw sockerr(recv, "gethostname: name or service not known");
136         }
137     }
138
139     private static InetAddress JavaDoc intoAddress(IRubyObject recv, String JavaDoc s) {
140         try {
141             byte[] bs = ByteList.plain(s);
142             return InetAddress.getByAddress(bs);
143         } catch(Exception JavaDoc e) {
144             throw sockerr(recv, "strtoaddr: " + e.toString());
145         }
146     }
147
148     private static String JavaDoc intoString(IRubyObject recv, InetAddress JavaDoc as) {
149         try {
150             return new String JavaDoc(ByteList.plain(as.getAddress()));
151         } catch(Exception JavaDoc 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); // AF_INET
163
ret[3] = args[0];
164         return runtime.newArrayNoCopy(ret);
165     }
166
167     public static IRubyObject gethostbyname(IRubyObject recv, IRubyObject hostname) {
168         try {
169             InetAddress JavaDoc 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); // AF_INET
175
ret[3] = runtime.newString(intoString(recv,addr));
176             return runtime.newArrayNoCopy(ret);
177         } catch(UnknownHostException JavaDoc e) {
178             throw sockerr(recv, "gethostbyname: name or service not known");
179         }
180     }
181
182     //def self.getaddrinfo(host, port, family = nil, socktype = nil, protocol = nil, flags = nil)
183
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 family = args[2];
190
IRubyObject socktype = args[3];
191             //IRubyObject protocol = args[4];
192
//IRubyObject flags = args[5];
193
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 JavaDoc[] addrs = InetAddress.getAllByName(host.isNil() ? null : host.convertToString().toString());
204             List JavaDoc l = new ArrayList JavaDoc();
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); // PF_INET
214
c[5] = r.newFixnum(1); // SOCK_STREAM
215
c[6] = r.newFixnum(6); // Protocol TCP
216
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); // PF_INET
225
c[5] = r.newFixnum(2); // SOCK_DRGRAM
226
c[6] = r.newFixnum(17); // Protocol UDP
227
l.add(r.newArrayNoCopy(c));
228                 }
229             }
230             return r.newArray(l);
231         } catch(UnknownHostException JavaDoc 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); // 0 == addr, 1 == flags
238

239         if (args[0] instanceof RubyArray) {
240             try {
241                 List JavaDoc 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 JavaDoc 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 }// RubySocket
255
Popular Tags