OSDN Git Service

70432a6a0d394a29c0aa67ee9023486981fd25d7
[android-x86/dalvik.git] / libcore / luni / src / main / java / org / apache / harmony / luni / platform / OSNetworkSystem.java
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17
18 // BEGIN android-note
19 // Address length was changed from long to int for performance reasons.
20 // Harmony implements INetworkSystem's methods with native methods; Android
21 // implements them with Java that call through to native wrappers.
22 // TODO: change the native code to eliminate the wrappers
23 // END android-note
24
25 package org.apache.harmony.luni.platform;
26
27 import java.io.FileDescriptor;
28 import java.io.IOException;
29 import java.net.DatagramPacket;
30 import java.net.InetAddress;
31 import java.net.SocketException;
32 import java.net.SocketImpl;
33 import java.net.UnknownHostException;
34 import java.nio.channels.Channel;
35 // BEGIN android-removed
36 // import java.nio.channels.SelectableChannel;
37 // END android-removed
38
39 /**
40  * This wraps native code that implements the INetworkSystem interface.
41  */
42 final class OSNetworkSystem implements INetworkSystem {
43
44     private static final int ERRORCODE_SOCKET_TIMEOUT = -209;
45     private static final int ERRORCODE_SOCKET_INTERRUPTED = -208;
46
47     private static final int INETADDR_REACHABLE = 0;
48
49     private static boolean isNetworkInited = false;
50
51     private static OSNetworkSystem singleton = new OSNetworkSystem();
52
53     /**
54      * Answers the unique instance of the OSNetworkSystem.
55      *
56      * @return the network system interface instance
57      */
58     public static OSNetworkSystem getOSNetworkSystem() {
59         return singleton;
60     }
61
62     // Can not be instantiated.
63     private OSNetworkSystem() {
64         super();
65     }
66
67     public void accept(FileDescriptor fdServer, SocketImpl newSocket,
68             FileDescriptor fdnewSocket, int timeout) throws IOException {
69         acceptSocketImpl(fdServer, newSocket, fdnewSocket, timeout);
70     }
71
72     static native void acceptSocketImpl(FileDescriptor fdServer,
73             SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
74             throws IOException;
75
76     // BEGIN android-removed
77     // public void acceptStreamSocket(FileDescriptor fdServer,
78     //         SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
79     //         throws IOException {
80     //     acceptStreamSocketImpl(fdServer, newSocket, fdnewSocket, timeout);
81     // }
82
83     // static native void acceptStreamSocketImpl(FileDescriptor fdServer,
84     //         SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
85     //         throws IOException;
86     // END android-removed
87
88     public int availableStream(FileDescriptor fd) throws SocketException {
89         return availableStreamImpl(fd);
90     }
91
92     static native int availableStreamImpl(FileDescriptor aFD) throws SocketException;
93
94     /**
95      * Associates a local address with a socket.
96      *
97      * @param fd
98      *            the socket descriptor
99      * @param port
100      *            the port number
101      * @param inetAddress
102      *            address to bind
103      * @throws SocketException
104      *             thrown if bind operation fails
105      */
106     public void bind(FileDescriptor fd, InetAddress inetAddress, int port) throws SocketException {
107         socketBindImpl(fd, port, inetAddress);
108     }
109
110     static native void socketBindImpl(FileDescriptor aFD, int port, InetAddress inetAddress) throws SocketException;
111
112     public int connect(FileDescriptor fd, int trafficClass,
113             InetAddress inetAddress, int port) throws IOException{
114         return connectSocketImpl(fd, trafficClass, inetAddress, port);
115     }
116
117     static native int connectSocketImpl(FileDescriptor aFD,
118             int trafficClass, InetAddress inetAddress, int port);
119
120     public void connectDatagram(FileDescriptor fd, int port,
121             int trafficClass, InetAddress inetAddress) throws SocketException {
122         connectDatagramImpl2(fd, port, trafficClass, inetAddress);
123     }
124
125     static native void connectDatagramImpl2(FileDescriptor aFD, int port,
126             int trafficClass, InetAddress inetAddress) throws SocketException;
127
128     public void connectStreamWithTimeoutSocket(FileDescriptor aFD,
129             int aport, int timeout, int trafficClass, InetAddress inetAddress)
130             throws IOException {
131         connectStreamWithTimeoutSocketImpl(aFD, aport, timeout, trafficClass,
132                 inetAddress);
133     }
134
135     static native void connectStreamWithTimeoutSocketImpl(FileDescriptor aFD,
136             int aport, int timeout, int trafficClass, InetAddress inetAddress)
137             throws IOException;
138
139     // BEGIN android-changed
140     // changed context from Long to byte[]
141     public int connectWithTimeout(FileDescriptor fd, int timeout,
142             int trafficClass, InetAddress inetAddress, int port, int step,
143             byte[] context) throws IOException {
144         return connectWithTimeoutSocketImpl(fd, timeout, trafficClass,
145                 inetAddress, port, step, context);
146     }
147
148     static native int connectWithTimeoutSocketImpl(FileDescriptor aFD,
149             int timeout, int trafficClass, InetAddress hostname, int port, int step,
150             byte[] context);
151     // END android-changed
152
153     public void createDatagramSocket(FileDescriptor fd,
154             boolean preferIPv4Stack) throws SocketException {
155         createDatagramSocketImpl(fd, preferIPv4Stack);
156     }
157
158     /*
159     * Allocate a datagram socket in the IP stack. The socket is associated with
160     * the <code>aFD</code>.
161     *
162     * @param aFD the FileDescriptor to associate with the socket @param
163     * preferIPv4Stack IP stack preference if underlying platform is V4/V6
164     * @exception SocketException upon an allocation error
165     */
166     static native void createDatagramSocketImpl(FileDescriptor aFD,
167             boolean preferIPv4Stack) throws SocketException;
168
169     public void createServerStreamSocket(FileDescriptor fd,
170             boolean preferIPv4Stack) throws SocketException {
171         createServerStreamSocketImpl(fd, preferIPv4Stack);
172     }
173
174     /*
175      * Answer the result of attempting to create a server stream socket in the
176      * IP stack. Any special options required for server sockets will be set by
177      * this method.
178      *
179      * @param aFD the socket FileDescriptor @param preferIPv4Stack if use IPV4
180      * @exception SocketException if an error occurs while creating the socket
181      */
182     static native void createServerStreamSocketImpl(FileDescriptor aFD,
183             boolean preferIPv4Stack) throws SocketException;
184
185     public void createStreamSocket(FileDescriptor fd,
186             boolean preferIPv4Stack) throws SocketException {
187         createStreamSocketImpl(fd, preferIPv4Stack);
188     }
189
190     static native void createStreamSocketImpl(FileDescriptor aFD,
191             boolean preferIPv4Stack) throws SocketException;
192
193     /**
194      * Disconnect the socket to a port and address
195      *a
196      * @param fd
197      *            the FileDescriptor associated with the socket
198      *
199      * @throws SocketException
200      *             if the disconnect fails
201      */
202     public void disconnectDatagram(FileDescriptor fd)
203             throws SocketException {
204         disconnectDatagramImpl(fd);
205     }
206
207     static native void disconnectDatagramImpl(FileDescriptor aFD)
208             throws SocketException;
209
210     public InetAddress getHostByAddr(byte[] ipAddress)
211             throws UnknownHostException {
212         // BEGIN android-changed
213         // Wallpaper fix for http://b/1851257. This  is a layering violation,
214         // but at least the method has the right return type.
215         // TODO: Fix the socket code to remove this method altogether.
216         return InetAddress.getByAddress(ipAddress);
217         // END android-changed
218     }
219     // BEGIN android-removed
220     // static native InetAddress getHostByAddrImpl(byte[] addr)
221     //         throws UnknownHostException;
222     // END android-removed
223
224     // BEGIN android-removed
225     public InetAddress getHostByName(String hostName,
226             boolean preferIPv6Addresses) throws UnknownHostException {
227         // BEGIN android-changed
228         // Wallpaper fix for http://b/1851257.
229         return InetAddress.getByName(hostName);
230         // END android-changed
231     }
232
233     // BEGIN android-removed
234     // static native InetAddress getHostByNameImpl(String addr,
235     //         boolean preferIPv6Addresses) throws UnknownHostException;
236     // END android-removed
237
238     public int getSocketFlags() {
239         return getSocketFlagsImpl();
240     }
241
242     static native int getSocketFlagsImpl();
243
244     public InetAddress getSocketLocalAddress(FileDescriptor fd,
245             boolean preferIPv6Addresses) {
246         return getSocketLocalAddressImpl(fd, preferIPv6Addresses);
247     }
248     static native InetAddress getSocketLocalAddressImpl(FileDescriptor aFD,
249             boolean preferIPv6Addresses);
250
251     /**
252      * Query the IP stack for the local port to which this socket is bound.
253      *
254      * @param aFD
255      *            the socket descriptor
256      * @param preferIPv6Addresses
257      *            address preference for nodes that support both IPv4 and IPv6
258      * @return the local port to which the socket is bound
259      */
260     public int getSocketLocalPort(FileDescriptor aFD,
261             boolean preferIPv6Addresses) {
262         return getSocketLocalPortImpl(aFD, preferIPv6Addresses);
263     }
264
265     static native int getSocketLocalPortImpl(FileDescriptor aFD,
266             boolean preferIPv6Addresses);
267
268     /**
269      * Query the IP stack for the nominated socket option.
270      *
271      * @param fd
272      *            the socket descriptor
273      * @param opt
274      *            the socket option type
275      * @return the nominated socket option value
276      * @throws SocketException
277      *             if the option is invalid
278      */
279     public Object getSocketOption(FileDescriptor fd, int opt)
280             throws SocketException {
281         return getSocketOptionImpl(fd, opt);
282     }
283
284     static native Object getSocketOptionImpl(FileDescriptor aFD, int opt)
285             throws SocketException;
286
287     public Channel inheritedChannel() {
288         return inheritedChannelImpl();
289     }
290
291     native Channel inheritedChannelImpl();
292
293     // BEGIN android-removed
294     // public boolean isReachableByICMP(final InetAddress dest,
295     //         InetAddress source, final int ttl, final int timeout) {
296     //     return INETADDR_REACHABLE == isReachableByICMPImpl(dest, source, ttl,
297     //     timeout);
298     // }
299
300     // native int isReachableByICMPImpl(InetAddress addr,
301     //         InetAddress local, int ttl, int timeout);
302     // END android-removed
303
304     public void listenStreamSocket(FileDescriptor aFD, int backlog)
305             throws SocketException {
306         listenStreamSocketImpl(aFD, backlog);
307     }
308
309     static native void listenStreamSocketImpl(FileDescriptor aFD, int backlog)
310             throws SocketException;
311
312     public void oneTimeInitialization(boolean jcl_supports_ipv6) {
313         if (!isNetworkInited) {
314             oneTimeInitializationImpl(jcl_supports_ipv6);
315             isNetworkInited = true;
316         }
317     }
318
319     native void oneTimeInitializationImpl (boolean jcl_supports_ipv6);
320
321     /**
322      * Peek on the socket, update <code>sender</code> address and answer the
323      * sender port.
324      *
325      * @param fd
326      *            the socket FileDescriptor
327      * @param sender
328      *            an InetAddress, to be updated with the sender's address
329      * @param receiveTimeout
330      *            the maximum length of time the socket should block, reading
331      * @return the sender port
332      *
333      * @throws IOException
334      *             upon an read error or timeout
335      */
336     public int peekDatagram(FileDescriptor fd, InetAddress sender,
337             int receiveTimeout) throws IOException {
338         return peekDatagramImpl(fd, sender, receiveTimeout);
339     }
340
341     static native int peekDatagramImpl(FileDescriptor aFD,
342             InetAddress sender, int receiveTimeout) throws IOException;
343
344     /**
345      * Read available bytes from the given file descriptor into a byte array.
346      *
347      * The read has an optional timeout parameter, which if non-zero is the
348      * length of time that the read will wait on a select call to see if any
349      * bytes are available for reading. If the timeout expires the method
350      * returns zero to indicate no bytes were read.
351      *
352      * @param fd
353      *            the socket file descriptor to read
354      * @param data
355      *            the byte array in which to store the results
356      * @param offset
357      *            the offset into the byte array in which to start reading the
358      *            results
359      * @param count
360      *            the maximum number of bytes to read
361      * @param timeout
362      *            the length of time to wait for the bytes, in milliseconds; or
363      *            zero to indicate no timeout applied. When there is no timeout
364      *            applied the read may block based upon socket options.
365      * @return number of bytes read, or zero if there were no bytes available
366      *         before the timeout occurred, or -1 to indicate the socket is
367      *         closed
368      * @throws IOException
369      *             if an underlying socket exception occurred
370      */
371     public int read(FileDescriptor fd, byte[] data, int offset, int count,
372             int timeout) throws IOException {
373         return readSocketImpl(fd, data, offset, count, timeout);
374     }
375
376     static native int readSocketImpl(FileDescriptor aFD, byte[] data,
377             int offset, int count, int timeout) throws IOException;
378
379     /**
380      * Read available bytes from the given file descriptor into OS memory at a
381      * given address.
382      *
383      * @param fd
384      *            the socket file descriptor to read
385      * @param address
386      *            the address of the memory in which to store the results
387      * @param count
388      *            the maximum number of bytes to read
389      * @param timeout
390      *            the length of time to wait for the bytes, in milliseconds
391      * @return number of bytes read, or zero if there were no bytes available
392      *         before the timeout occurred, or -1 to indicate the socket is
393      *         closed
394      * @throws IOException
395      *             if an underlying socket exception occurred
396      */
397     public int readDirect(FileDescriptor fd, int address, int offset, int count,
398             int timeout) throws IOException {
399         return readSocketDirectImpl(fd, address, offset, count, timeout);
400     }
401
402     static native int readSocketDirectImpl(FileDescriptor aFD, int address, int offset, int count,
403             int timeout) throws IOException;
404
405     /**
406      * Receive data on the socket into the specified buffer. The packet fields
407      * <code>data</code> & <code>length</code> are passed in addition to
408      * <code>packet</code> to eliminate the JNI field access calls.
409      *
410      * @param fd
411      *            the socket FileDescriptor
412      * @param packet
413      *            the DatagramPacket to receive into
414      * @param data
415      *            the data buffer of the packet
416      * @param offset
417      *            the offset in the data buffer
418      * @param length
419      *            the length of the data buffer in the packet
420      * @param receiveTimeout
421      *            the maximum length of time the socket should block, reading
422      * @param peek
423      *            indicates to peek at the data
424      * @return number of data received
425      * @throws IOException
426      *             upon an read error or timeout
427      */
428     public int receiveDatagram(FileDescriptor fd, DatagramPacket packet,
429             byte[] data, int offset, int length, int receiveTimeout,
430             boolean peek) throws IOException {
431         return receiveDatagramImpl(fd, packet, data, offset, length,
432                 receiveTimeout, peek);
433     }
434
435     static native int receiveDatagramImpl(FileDescriptor aFD,
436             DatagramPacket packet, byte[] data, int offset, int length,
437             int receiveTimeout, boolean peek) throws IOException;
438
439     public int receiveDatagramDirect(FileDescriptor fd,
440             DatagramPacket packet, int address, int offset, int length,
441             int receiveTimeout, boolean peek) throws IOException {
442         return receiveDatagramDirectImpl(fd, packet, address, offset, length,
443                 receiveTimeout, peek);
444     }
445
446     static native int receiveDatagramDirectImpl(FileDescriptor aFD,
447             DatagramPacket packet, int address, int offset, int length,
448             int receiveTimeout, boolean peek) throws IOException;
449
450     /**
451      * Receive at most <code>count</code> bytes into the buffer
452      * <code>data</code> at the <code>offset</code> on the socket.
453      *
454      * @param aFD
455      *            the socket FileDescriptor
456      * @param data
457      *            the receive buffer
458      * @param offset
459      *            the offset into the buffer
460      * @param count
461      *            the max number of bytes to receive
462      * @param timeout
463      *            the max time the read operation should block waiting for data
464      * @return the actual number of bytes read
465      * @throws IOException
466      * @throws SocketException
467      *             if an error occurs while reading
468      * @deprecated use {@link #read(FileDescriptor, byte[], int, int, int)}
469      */
470     public int receiveStream(FileDescriptor aFD, byte[] data,
471             int offset, int count, int timeout) throws IOException {
472         return receiveStreamImpl(aFD, data, offset, count, timeout);
473     }
474
475     static native int receiveStreamImpl(FileDescriptor aFD, byte[] data,
476             int offset, int count, int timeout) throws IOException;
477
478     // BEGIN android-added
479     /**
480      * Send <code>count</code> bytes from the buffer <code>data</code> at
481      * the <code>offset</code>, on the socket.
482      *
483      * @param fd
484      *
485      * @param data the send buffer @param offset the offset into the buffer
486      * @param count the number of bytes to receive @return int the actual number
487      * of bytes sent @throws IOException @exception SocketException if an error
488      * occurs while writing
489      */
490     public int sendStream(FileDescriptor fd, byte[] data, int offset, int count)
491             throws IOException {
492         return sendStreamImpl(fd, data, offset, count);
493     }
494
495     static native int sendStreamImpl(FileDescriptor fd, byte[] data,
496             int offset, int count) throws IOException;
497     // END android-added
498
499     /**
500      * Recieve data on the connected socket into the specified buffer. The
501      * packet fields <code>data</code> and <code>length</code> are passed in
502      * addition to <code>packet</code> to eliminate the JNI field access calls.
503      *
504      * @param fd
505      *            the socket FileDescriptor
506      * @param packet
507      *            the DatagramPacket to receive into
508      * @param data
509      *            the data buffer of the packet
510      * @param offset
511      *            the offset in the data buffer
512      * @param length
513      *            the length of the data buffer in the packet
514      * @param receiveTimeout
515      *            the maximum length of time the socket should block, reading
516      * @param peek
517      *            indicates to peek at the data
518      * @return number of data received
519      * @throws IOException
520      *             upon an read error or timeout
521      */
522     public int recvConnectedDatagram(FileDescriptor fd,
523             DatagramPacket packet, byte[] data, int offset, int length,
524             int receiveTimeout, boolean peek) throws IOException {
525         return recvConnectedDatagramImpl(fd, packet, data, offset, length,
526                 receiveTimeout, peek);
527     }
528
529     static native int recvConnectedDatagramImpl(FileDescriptor aFD,
530             DatagramPacket packet, byte[] data, int offset, int length,
531             int receiveTimeout, boolean peek) throws IOException;
532
533     public int recvConnectedDatagramDirect(FileDescriptor aFD, DatagramPacket packet, int address,
534             int offset, int length, int receiveTimeout, boolean peek)
535             throws IOException {
536         return recvConnectedDatagramDirectImpl(aFD, packet, address, offset, length, receiveTimeout, peek);
537     }
538
539     static native int recvConnectedDatagramDirectImpl(FileDescriptor aFD,
540             DatagramPacket packet, int address, int offset, int length,
541             int receiveTimeout, boolean peek) throws IOException;
542
543     /**
544      * Select the given file descriptors for read and write operations.
545      *
546      * The file descriptors passed in as readFDs will be selected for read-ready
547      * operations, and those in the writeFDs will be selected for write-ready
548      * operations. A file descriptor can appear in either or both array, and
549      * must not be <code>null</code>. If the file descriptor is closed during
550      * the select the behavior depends upon the underlying OS.
551      *
552      * Upon return the result is a single array of length
553      * <code>readFDs.length</code> + <code>writeFDs.length</code> laid out as
554      * the result of the select operation on the corresponding file descriptors.
555      *
556      * @param readFDs
557      *            all sockets interested in read and accept
558      * @param writeFDs
559      *            all sockets interested in write and connect
560      * @param timeout
561      *            timeout in milliseconds
562      * @return each element describes the corresponding state of the descriptor
563      *         in the read and write arrays.
564      * @throws SocketException
565      */
566     public int[] select(FileDescriptor[] readFDs, FileDescriptor[] writeFDs,
567             long timeout) throws SocketException {
568         int countRead = readFDs.length;
569         int countWrite = writeFDs.length;
570         int result = 0;
571         if (0 == countRead + countWrite) {
572             return (new int[0]);
573         }
574         int[] flags = new int[countRead + countWrite];
575
576         assert validateFDs(readFDs, writeFDs) : "Invalid file descriptor arrays"; //$NON-NLS-1$
577
578         // handle timeout in native
579         result = selectImpl(readFDs, writeFDs, countRead, countWrite, flags,
580                 timeout);
581
582         if (0 <= result) {
583             return flags;
584         }
585         if (ERRORCODE_SOCKET_TIMEOUT == result ||
586                 ERRORCODE_SOCKET_INTERRUPTED == result) {
587             return new int[0];
588         }
589         throw new SocketException();
590     }
591
592     static native int selectImpl(FileDescriptor[] readfd,
593             FileDescriptor[] writefd, int cread, int cwirte, int[] flags,
594             long timeout);
595
596     /**
597      * Send the <code>data</code> to the address and port to which the was
598      * connected and <code>port</code>.
599      *
600      * @param fd
601      *            the socket FileDescriptor
602      * @param data
603      *            the data buffer of the packet
604      * @param offset
605      *            the offset in the data buffer
606      * @param length
607      *            the length of the data buffer in the packet
608      * @param bindToDevice
609      *            not used, current kept in case needed as was the case for
610      *            sendDatagramImpl
611      * @return number of data send
612      * @throws IOException
613      *             upon an read error or timeout
614      */
615     public int sendConnectedDatagram(FileDescriptor fd, byte[] data,
616             int offset, int length, boolean bindToDevice) throws IOException {
617         return sendConnectedDatagramImpl(fd, data, offset, length, bindToDevice);
618     }
619
620     static native int sendConnectedDatagramImpl(FileDescriptor fd,
621             byte[] data, int offset, int length, boolean bindToDevice)
622             throws IOException;
623
624     public int sendConnectedDatagramDirect(FileDescriptor fd,
625             int address, int offset, int length, boolean bindToDevice)
626             throws IOException {
627         return sendConnectedDatagramDirectImpl(fd, address, offset, length, bindToDevice);
628     }
629     static native int sendConnectedDatagramDirectImpl(FileDescriptor fd,
630             int address, int offset, int length, boolean bindToDevice)
631             throws IOException;
632
633     /**
634      * Send the <code>data</code> to the nominated target <code>address</code>
635      * and <code>port</code>. These values are derived from the DatagramPacket
636      * to reduce the field calls within JNI.
637      *
638      * @param fd
639      *            the socket FileDescriptor
640      * @param data
641      *            the data buffer of the packet
642      * @param offset
643      *            the offset in the data buffer
644      * @param length
645      *            the length of the data buffer in the packet
646      * @param port
647      *            the target host port
648      * @param bindToDevice
649      *            if bind to device
650      * @param trafficClass
651      *            the traffic class to be used when the datagram is sent
652      * @param inetAddress
653      *            address to connect to.
654      * @return number of data send
655      *
656      * @throws IOException
657      *             upon an read error or timeout
658      */
659     public int sendDatagram(FileDescriptor fd, byte[] data, int offset,
660             int length, int port, boolean bindToDevice, int trafficClass,
661             InetAddress inetAddress) throws IOException {
662         return sendDatagramImpl(fd, data, offset, length, port, bindToDevice,
663                 trafficClass, inetAddress);
664     }
665
666     static native int sendDatagramImpl(FileDescriptor fd, byte[] data, int offset,
667             int length, int port, boolean bindToDevice, int trafficClass,
668             InetAddress inetAddress) throws IOException;
669
670     public int sendDatagram2(FileDescriptor fd, byte[] data, int offset,
671             int length, int port, InetAddress inetAddress) throws IOException {
672         return sendDatagramImpl2(fd, data, offset, length, port, inetAddress);
673     }
674
675     static native int sendDatagramImpl2(FileDescriptor fd, byte[] data,
676             int offset, int length, int port, InetAddress inetAddress) throws IOException;
677
678
679     public int sendDatagramDirect(FileDescriptor fd, int address,
680             int offset, int length, int port, boolean bindToDevice,
681             int trafficClass, InetAddress inetAddress) throws IOException {
682         return sendDatagramDirectImpl(fd, address, offset, length, port, bindToDevice,
683                 trafficClass, inetAddress);
684     }
685
686     static native int sendDatagramDirectImpl(FileDescriptor fd, int address,
687             int offset, int length, int port, boolean bindToDevice,
688             int trafficClass, InetAddress inetAddress) throws IOException;
689
690     public void sendUrgentData(FileDescriptor fd, byte value) {
691         sendUrgentDataImpl(fd, value);
692     }
693
694     static native void sendUrgentDataImpl(FileDescriptor fd, byte value);
695
696     public void setInetAddress(InetAddress sender, byte[] address) {
697         setInetAddressImpl(sender, address);
698     }
699
700     native void setInetAddressImpl(InetAddress sender, byte[] address);
701
702     public void setNonBlocking(FileDescriptor fd, boolean block)
703             throws IOException {
704         setNonBlockingImpl(fd, block);
705     }
706
707     static native void setNonBlockingImpl(FileDescriptor aFD, boolean block);
708
709     /**
710      * Set the nominated socket option in the IP stack.
711      *
712      * @param aFD
713      *            the socket descriptor @param opt the option selector @param
714      *            optVal the nominated option value
715      *
716      * @throws SocketException
717      *             if the option is invalid or cannot be set
718      */
719     public void setSocketOption(FileDescriptor aFD, int opt,
720             Object optVal) throws SocketException {
721         setSocketOptionImpl(aFD, opt, optVal);
722     }
723
724     static native void setSocketOptionImpl(FileDescriptor aFD, int opt,
725             Object optVal) throws SocketException;
726
727     public void shutdownInput(FileDescriptor descriptor) throws IOException {
728         shutdownInputImpl(descriptor);
729     }
730
731     private native void shutdownInputImpl(FileDescriptor descriptor)
732             throws IOException;
733
734     public void shutdownOutput(FileDescriptor fd) throws IOException {
735         shutdownOutputImpl(fd);
736     }
737
738     private native void shutdownOutputImpl(FileDescriptor descriptor)
739             throws IOException;
740     /**
741      * Close the socket in the IP stack.
742      *
743      * @param fd
744      *            the socket descriptor
745      */
746     public void socketClose(FileDescriptor fd) throws IOException {
747         socketCloseImpl(fd);
748     }
749
750     static native void socketCloseImpl(FileDescriptor fD);
751
752     public boolean supportsUrgentData(FileDescriptor fd) {
753         return supportsUrgentDataImpl(fd);
754     }
755
756     static native boolean supportsUrgentDataImpl(FileDescriptor fd);
757
758     /*
759     * Used to check if the file descriptor arrays are valid before passing them
760     * into the select native call.
761     */
762     private boolean validateFDs(FileDescriptor[] readFDs,
763             FileDescriptor[] writeFDs) {
764         for (FileDescriptor fd : readFDs) {
765             // Also checks fd not null
766             if (!fd.valid()) {
767                 return false;
768             }
769         }
770         for (FileDescriptor fd : writeFDs) {
771             if (!fd.valid()) {
772                 return false;
773             }
774         }
775         return true;
776     }
777
778     /**
779      * Write bytes from a byte array to a socket.
780      *
781      * @param fd
782      *            the socket on which to write the bytes
783      * @param data
784      *            the array containing the bytes to be written
785      * @param offset
786      *            the offset in the byte array from which to take the bytes
787      * @param count
788      *            the maximum number of bytes to be written. Callers are trusted
789      *            not to send values of length+count that are larger than
790      *            data.length
791      * @return the actual number of bytes written, which will be between zero
792      *         and count
793      * @throws IOException
794      *             if there is an underlying socket problem
795      */
796     public int write(FileDescriptor fd, byte[] data, int offset, int count)
797             throws IOException {
798         return writeSocketImpl(fd, data, offset, count);
799     }
800
801     static native int writeSocketImpl(FileDescriptor fd, byte[] data, int offset,
802             int count) throws IOException;
803
804
805     /**
806      * Write bytes from the given address to a socket.
807      *
808      * @param fd
809      *            the socket on which to write the bytes
810      * @param address
811      *            the start address of the bytes to be written
812      * @param count
813      *            the maximum number of bytes to be written
814      * @return the actual number of bytes written, which will be between zero
815      *         and count
816      * @throws IOException
817      *             if there is an underlying socket problem
818      */
819     public int writeDirect(FileDescriptor fd, int address, int offset, int count)
820             throws IOException {
821         return writeSocketDirectImpl(fd, address, offset, count);
822     }
823
824     static native int writeSocketDirectImpl(FileDescriptor fd, int address, int offset, int count)
825             throws IOException;
826 }