Source code: com/act365/net/GeneralDatagramSocketImpl.java
1 /*
2 * JSocket Wrench
3 *
4 * Copyright (C) act365.com October 2003
5 *
6 * Web site: http://www.act365.com/wrench
7 * E-mail: developers@act365.com
8 *
9 * The JSocket Wrench library adds support for low-level Internet protocols
10 * to the Java programming language.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the Free
14 * Software Foundation; either version 2 of the License, or (at your option)
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
20 * Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27 package com.act365.net;
28
29 import java.io.*;
30 import java.net.*;
31
32 /**
33 * GeneralDatagramSocketImpl extends <code>java.net.DatagramSocketImpl</code>
34 * and provides native implementations of all of its abstract methods. The
35 * class remains abstract because it leaves its <code>create()</code> method
36 * undefined - it is up to subclasses to specify the parameters that will
37 * be used to create the underlying socket.
38 */
39
40 public abstract class GeneralDatagramSocketImpl extends DatagramSocketImpl {
41
42 /**
43 Creates a new unconnected socket. The socket is allowed to be of any type
44 and use any protocol supported by the underlying operating system. The method
45 <code>create()</code> - note no arguments - should be defined in a subclass
46 and call the version in the superclass with the parameters set
47 appropriately. When a raw socket is set up, the user has the option to write
48 his own IP header sockets (set <code>headerincluded</code> to <code>true</code>)
49 or to allow the operating system to write the headers. NB The option does
50 not exist on Windows, where the <code>IP_HDRINCL</code> symbol is
51 unsupported.
52 @see com.act365.net.SocketConstants
53 @param socketType the socket type as defined in <code>SocketConstants</code> e.g. SOCK_RAW
54 @param protocol the protocol as defined in <code>SocketConstants</code> e.g. IPPROTO_UDP
55 @param headerincluded whether the user will complete the IP header
56 */
57
58 public void create ( int socketType , int protocol , boolean headerincluded ) throws SocketException {
59
60 int sd = _socket( SocketConstants.AF_INET , socketType , protocol , headerincluded );
61
62 fd = new FileDescriptor();
63
64 setSocketDescriptor( fd , sd );
65 }
66
67 native static int _socket( int addressFamily , int socketType , int protocol , boolean headerincluded );
68
69 /**
70 Binds this socket to a local port.
71 @param localPort number of the local port
72 @param inetAddress local IP address
73 */
74
75 public void bind( int localPort , InetAddress inetAddress ) throws SocketException {
76
77 _bind( getSocketDescriptor( fd ) , inetAddress.getAddress() , localPort );
78
79 this.localPort = localPort ;
80 }
81
82 native static int _bind( int sd , byte[] ipAddress , int port );
83
84 /**
85 Closes this socket.
86 */
87
88 public void close() {
89
90 _close( getSocketDescriptor( fd ) );
91 }
92
93 native static int _close( int sd );
94
95 /**
96 Polls until a datagram packet is received. Once received, the parameter
97 <em>sender</em> is populated with the address of the sender and the
98 port number is returned as an <code>int</code>. Note that the JDK1.4 API
99 documentation states that the IP address should be returned as an <code>int</code>
100 - however, the JDK1.1 API documentation states that the port number should be
101 returned. I have implemented the JDK1.1 behaviour because it seems more
102 sensible - an IP address is always stored in an <code>InetAddress</code>
103 object in Java.
104 @param sender address of sender - to be populated by the function call
105 @return port used by sender
106 */
107
108 public int peek( InetAddress sender ) throws IOException {
109 byte[] buffer = new byte[0];
110 DatagramPacket dgram = new DatagramPacket( buffer , buffer.length );
111 dgram.setAddress( GeneralSocketImpl.createInetAddress( SocketConstants.AF_INET , new byte[]{0,0,0,0} ));
112 _receive( getSocketDescriptor( fd ) , dgram , SocketConstants.MSG_PEEK );
113 sender = dgram.getAddress();
114 return dgram.getPort();
115 }
116
117 /**
118 * Extracts the next DatagramPacket and returns the port number. Note
119 * that the behaviour differs from that described in the JDK1.4
120 * documentation.
121 * @see peek
122 * @param p next packet received
123 * @return port to have received the packet
124 */
125
126 public int peekData( DatagramPacket p ) throws IOException {
127 byte[] buffer = new byte[ 0 ];
128 p.setData( buffer );
129 p.setAddress( GeneralSocketImpl.createInetAddress( SocketConstants.AF_INET , new byte[]{0,0,0,0} ));
130 _receive( getSocketDescriptor( fd ) , p , SocketConstants.MSG_PEEK );
131 return p.getPort();
132 }
133
134 /**
135 Reads a datagram packet.
136 @param dgram packet to be populated
137 */
138
139 public void receive( DatagramPacket dgram ) throws IOException {
140 dgram.setAddress( GeneralSocketImpl.createInetAddress( SocketConstants.AF_INET , new byte[]{0,0,0,0} ));
141 _receive( getSocketDescriptor( fd ) , dgram , 0 );
142 }
143
144 native static void _receive( int sd , DatagramPacket dgram , int flags );
145
146 /**
147 Sends a datagram packet.
148 @param dgram packet to be sent
149 */
150
151 public void send( DatagramPacket dgram ) throws IOException {
152
153 _send( getSocketDescriptor( fd ) ,
154 dgram.getAddress().getAddress() ,
155 dgram.getPort() ,
156 dgram.getData() ,
157 dgram.getLength() );
158 }
159
160 native static void _send( int sd , byte[] ipAddress , int port , byte[] data , int length );
161
162 /**
163 Retrieves time-to-live for multicast sockets.
164 NB Multicast sockets are not yet supported.
165 */
166
167 public int getTimeToLive() throws IOException {
168 throw new IOException("Multicast sockets not supported");
169 }
170
171 /**
172 Retrieves time-to-live for multicast sockets.
173 NB Multicast sockets are not yet supported.
174 The method leads to a deprecation warning in JDK1.3 but has to be
175 provided if <code>java.net.DatagramSocketImpl</code> is to be extended.
176 */
177
178 public byte getTTL() throws IOException {
179 throw new IOException("Multicast sockets not supported");
180 }
181
182 /**
183 Joins a multicast group. (JDK1.3)
184 NB Multicast sockets are not yet supported.
185 */
186
187 public void join( InetAddress groupAddr ) throws IOException {
188 throw new IOException("Multicast sockets not supported");
189 }
190
191 /**
192 Joins a multicast group. (JDK1.4)
193 NB Multicast sockets are not yet supported.
194 */
195
196 public void joinGroup( SocketAddress mcastaddr , NetworkInterface netIf ) throws IOException {
197 throw new IOException("Multicast sockets not supported");
198 }
199
200 /**
201 Leaves a multicast group. (JDK1.3)
202 NB Multicast sockets are not yet supported.
203 */
204
205 public void leave( InetAddress groupAddr ) throws IOException {
206 throw new IOException("Multicast sockets not supported");
207 }
208
209 /**
210 Leaves a multicast group. (JDK1.4)
211 NB Multicast sockets are not yet supported.
212 */
213
214 public void leaveGroup( SocketAddress mcastaddr , NetworkInterface netIf ) throws IOException {
215 throw new IOException("Multicast sockets not supported");
216 }
217
218 /**
219 Sets time-to-live for multicast sockets.
220 NB Multicast sockets are not yet supported.
221 */
222
223 public void setTimeToLive( int ttl ) throws IOException {
224 throw new IOException("Multicast sockets not supported");
225 }
226
227 /**
228 Sets time-to-live for multicast sockets.
229 NB Multicast sockets are not yet supported.
230 The method leads to a deprecation warning in JDK1.3 but has to be
231 provided if <code>java.net.DatagramSocketImpl</code> is to be extended.
232 */
233
234 public void setTTL( byte ttl ) throws IOException {
235 throw new IOException("Multicast sockets not supported");
236 }
237
238 /**
239 Gets the socket descriptor from a <code>java.io.FileDescriptor</code> object.
240 NB Java provides no public access to the value of the descriptor so
241 it has to be extracted using native code.
242 */
243
244 public static int getSocketDescriptor( FileDescriptor fd ){
245 return _getSocketDescriptor( fd );
246 }
247
248 native static int _getSocketDescriptor( FileDescriptor fd );
249
250 /**
251 Sets the socket descriptor for a <code>java.io.FileDescriptor</code> object.
252 NB Java provides no public access to the descriptor so its value has to
253 be set using native code.
254 */
255
256 public static void setSocketDescriptor( FileDescriptor fd , int sd ){
257 _setSocketDescriptor( fd , sd );
258 }
259
260 native static void _setSocketDescriptor( FileDescriptor fd , int sd );
261
262 /**
263 Sets the value of a socket option. The value has to be an
264 <code>Integer</code> object.
265 @param optID option as defined in <code>java.net.SocketConstants</code>
266 @param value an <code>Integer</code> object that wraps the new value
267 */
268
269 public void setOption( int optID , Object value ) throws SocketException {
270
271 if( _setOption( getSocketDescriptor( fd ) , optID , value ) < 0 ){
272 throw new SocketException();
273 }
274 }
275
276 static native int _setOption( int socketDescriptor , int optionName , Object newValue );
277
278 /**
279 Gets the value of a socket option. The returned value will be an
280 <code>Integer</code> object.
281 @param optID option as defined in <code>java.net.SocketConstants</code>
282 */
283
284 public Object getOption( int optID ) throws SocketException {
285
286 Object value = _getOption( getSocketDescriptor( fd ) , optID );
287
288 return value ;
289 }
290
291 static native Object _getOption( int socketDescriptor , int optionName ) throws SocketException ;
292 };
293
294