1 /* PlainDatagramSocketImpl.c - Native methods for PlainDatagramSocketImpl class
2 Copyright (C) 1998 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 /* do not move; needed here because of some macro definitions */
39 #include <config.h>
40
41 #include <stdlib.h>
42 #include <stdio.h>
43 #include <string.h>
44 #include <assert.h>
45
46 #include <jni.h>
47 #include <jcl.h>
48
49 #include "javanet.h"
50
51 #include "target_native.h"
52 #ifndef WITHOUT_NETWORK
53 #include "target_native_network.h"
54 #endif /* WITHOUT_NETWORK */
55
56 #include "gnu_java_net_PlainDatagramSocketImpl.h"
57
58 /*
59 * Note that most of the functions in this module simply redirect to another
60 * internal function. Why? Because many of these functions are shared
61 * with PlainSocketImpl.
62 */
63
64 /*************************************************************************/
65
66 /*
67 * Creates a new datagram socket
68 */
69 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainDatagramSocketImpl_create(JNIEnv * env,jobject obj)70 Java_gnu_java_net_PlainDatagramSocketImpl_create (JNIEnv * env, jobject obj)
71 {
72 assert (env != NULL);
73 assert ((*env) != NULL);
74
75 #ifndef WITHOUT_NETWORK
76 _javanet_create (env, obj, 0);
77 #else /* not WITHOUT_NETWORK */
78 #endif /* not WITHOUT_NETWORK */
79 }
80
81 /*************************************************************************/
82
83 /*
84 * Close the socket.
85 */
86 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainDatagramSocketImpl_close(JNIEnv * env,jobject obj)87 Java_gnu_java_net_PlainDatagramSocketImpl_close (JNIEnv * env, jobject obj)
88 {
89 assert (env != NULL);
90 assert ((*env) != NULL);
91
92 #ifndef WITHOUT_NETWORK
93 _javanet_close (env, obj, 0);
94 #else /* not WITHOUT_NETWORK */
95 #endif /* not WITHOUT_NETWORK */
96 }
97
98 /*************************************************************************/
99
100 /*
101 * This method binds the specified address to the specified local port.
102 * Note that we have to set the local address and local port public instance
103 * variables.
104 */
105 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainDatagramSocketImpl_bind(JNIEnv * env,jobject obj,jint port,jobject addr)106 Java_gnu_java_net_PlainDatagramSocketImpl_bind (JNIEnv * env, jobject obj,
107 jint port, jobject addr)
108 {
109 assert (env != NULL);
110 assert ((*env) != NULL);
111
112 #ifndef WITHOUT_NETWORK
113 _javanet_bind (env, obj, addr, port, 0);
114 #else /* not WITHOUT_NETWORK */
115 #endif /* not WITHOUT_NETWORK */
116 }
117
118 /*************************************************************************/
119
120 /*
121 * This method sets the specified option for a socket
122 */
123 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainDatagramSocketImpl_setOption(JNIEnv * env,jobject obj,jint option_id,jobject val)124 Java_gnu_java_net_PlainDatagramSocketImpl_setOption (JNIEnv * env,
125 jobject obj,
126 jint option_id,
127 jobject val)
128 {
129 assert (env != NULL);
130 assert ((*env) != NULL);
131
132 #ifndef WITHOUT_NETWORK
133 _javanet_set_option (env, obj, option_id, val);
134 #else /* not WITHOUT_NETWORK */
135 #endif /* not WITHOUT_NETWORK */
136 }
137
138 /*************************************************************************/
139
140 /*
141 * This method sets the specified option for a socket
142 */
143 JNIEXPORT jobject JNICALL
Java_gnu_java_net_PlainDatagramSocketImpl_getOption(JNIEnv * env,jobject obj,jint option_id)144 Java_gnu_java_net_PlainDatagramSocketImpl_getOption (JNIEnv * env,
145 jobject obj,
146 jint option_id)
147 {
148 assert (env != NULL);
149 assert ((*env) != NULL);
150
151 #ifndef WITHOUT_NETWORK
152 return (_javanet_get_option (env, obj, option_id));
153 #else /* not WITHOUT_NETWORK */
154 return NULL;
155 #endif /* not WITHOUT_NETWORK */
156 }
157
158 /*************************************************************************/
159
160 /*
161 * Reads a buffer from a remote host
162 */
163 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainDatagramSocketImpl_receive0(JNIEnv * env,jobject obj,jobject packet)164 Java_gnu_java_net_PlainDatagramSocketImpl_receive0 (JNIEnv * env, jobject obj,
165 jobject packet)
166 {
167 #ifndef WITHOUT_NETWORK
168 int addr, port, bytes_read;
169 unsigned int maxlen, offset;
170 jclass cls, addr_cls;
171 jfieldID fid;
172 jmethodID mid;
173 jarray arr;
174 unsigned char octets[4];
175 char ip_str[16];
176 jobject ip_str_obj, addr_obj;
177
178 assert (env != NULL);
179 assert ((*env) != NULL);
180
181 addr = 0;
182 port = 0;
183 maxlen = 0;
184 offset = 0;
185 bytes_read = 0;
186
187 if (packet == NULL)
188 {
189 JCL_ThrowException (env, "java/lang/NullPointerException",
190 "Null datagram packet");
191 return;
192 }
193
194 /* Get the buffer from the packet */
195 cls = (*env)->GetObjectClass (env, packet);
196 if (cls == NULL)
197 {
198 JCL_ThrowException (env, IO_EXCEPTION, "Internal error");
199 return;
200 }
201
202 mid = (*env)->GetMethodID (env, cls, "getData", "()[B");
203 if (mid == NULL)
204 {
205 JCL_ThrowException (env, IO_EXCEPTION, "Internal error: getData");
206 return;
207 }
208
209 arr = (*env)->CallObjectMethod (env, packet, mid);
210 if ((*env)->ExceptionOccurred (env))
211 return;
212 if (arr == NULL)
213 {
214 JCL_ThrowException (env, IO_EXCEPTION, "Internal error: call getData");
215 return;
216 }
217
218 /* Now get the offset from the packet */
219 mid = (*env)->GetMethodID (env, cls, "getOffset", "()I");
220 if (mid == NULL)
221 {
222 JCL_ThrowException (env, IO_EXCEPTION, "Internal error: getOffset");
223 return;
224 }
225
226 offset = (*env)->CallIntMethod (env, packet, mid);
227 if ((*env)->ExceptionOccurred (env))
228 return;
229
230 DBG ("PlainDatagramSocketImpl.receive(): Got the offset\n");
231
232 /* Now get the maximal available length from the packet */
233 fid = (*env)->GetFieldID (env, cls, "maxlen", "I");
234 if (fid == NULL)
235 {
236 JCL_ThrowException (env, IO_EXCEPTION, "Internal error: maxlen");
237 return;
238 }
239
240 maxlen = (*env)->GetIntField (env, packet, fid);
241 if ((*env)->ExceptionOccurred (env))
242 return;
243
244 /* Receive the packet */
245 /* should we try some sort of validation on the length? */
246 bytes_read =
247 _javanet_recvfrom (env, obj, arr, offset, maxlen, &addr, &port);
248 if ((*env)->ExceptionOccurred (env))
249 return;
250 if (bytes_read == -1)
251 {
252 JCL_ThrowException (env, IO_EXCEPTION, "Internal error: receive");
253 return;
254 }
255
256 DBG ("PlainDatagramSocketImpl.receive(): Received packet\n");
257
258 /* Store the address */
259 TARGET_NATIVE_NETWORK_INT_TO_IPADDRESS_BYTES (addr,
260 octets[0],
261 octets[1],
262 octets[2], octets[3]);
263 sprintf (ip_str, "%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3]);
264 ip_str_obj = (*env)->NewStringUTF (env, ip_str);
265 if (ip_str_obj == NULL)
266 {
267 JCL_ThrowException (env, IO_EXCEPTION, "Internal error: new string");
268 return;
269 }
270
271 addr_cls = (*env)->FindClass (env, "java/net/InetAddress");
272 if (addr_cls == NULL)
273 {
274 JCL_ThrowException (env, IO_EXCEPTION,
275 "Internal error: InetAddress class");
276 return;
277 }
278 DBG ("PlainDatagramSocketImpl.receive(): Found InetAddress class\n");
279
280 mid = (*env)->GetStaticMethodID (env, addr_cls, "getByName",
281 "(Ljava/lang/String;)Ljava/net/InetAddress;");
282 if (mid == NULL)
283 {
284 JCL_ThrowException (env, IO_EXCEPTION, "Internal Error");
285 return;
286 }
287 DBG
288 ("PlainDatagramSocketImpl.receive(): Found InetAddress.getByName method\n");
289
290 addr_obj = (*env)->CallStaticObjectMethod (env, addr_cls, mid, ip_str_obj);
291 if ((*env)->ExceptionOccurred (env))
292 return;
293
294 mid = (*env)->GetMethodID (env, cls, "setAddress",
295 "(Ljava/net/InetAddress;)V");
296 if (mid == NULL)
297 {
298 JCL_ThrowException (env, IO_EXCEPTION, "Internal error: setAddress");
299 return;
300 }
301
302 (*env)->CallVoidMethod (env, packet, mid, addr_obj);
303 if ((*env)->ExceptionOccurred (env))
304 return;
305
306 DBG ("PlainDatagramSocketImpl.receive(): Stored the address\n");
307
308 /* Store the port */
309 mid = (*env)->GetMethodID (env, cls, "setPort", "(I)V");
310 if (mid == NULL)
311 {
312 JCL_ThrowException (env, IO_EXCEPTION, "Internal error: setPort");
313 return;
314 }
315
316 (*env)->CallVoidMethod (env, packet, mid, port);
317 if ((*env)->ExceptionOccurred (env))
318 return;
319
320 DBG ("PlainDatagramSocketImpl.receive(): Stored the port\n");
321
322 /* Store back the length */
323 fid = (*env)->GetFieldID (env, cls, "length", "I");
324 if (fid == NULL)
325 {
326 JCL_ThrowException (env, IO_EXCEPTION, "Internal error: length");
327 return;
328 }
329
330 (*env)->SetIntField (env, packet, fid, bytes_read);
331 if ((*env)->ExceptionOccurred (env))
332 return;
333
334 DBG ("PlainDatagramSocketImpl.receive(): Stored the length\n");
335 #else /* not WITHOUT_NETWORK */
336 #endif /* not WITHOUT_NETWORK */
337 }
338
339 /*************************************************************************/
340
341 /*
342 * Writes a buffer to the remote host
343 */
344 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainDatagramSocketImpl_sendto(JNIEnv * env,jobject obj,jobject addr,jint port,jarray buf,jint offset,jint len)345 Java_gnu_java_net_PlainDatagramSocketImpl_sendto (JNIEnv * env, jobject obj,
346 jobject addr, jint port,
347 jarray buf, jint offset,
348 jint len)
349 {
350 #ifndef WITHOUT_NETWORK
351 jint netAddress;
352
353 assert (env != NULL);
354 assert ((*env) != NULL);
355
356 netAddress = _javanet_get_netaddr (env, addr);
357 if ((*env)->ExceptionOccurred (env))
358 return;
359
360 DBG ("PlainDatagramSocketImpl.sendto(): have addr\n");
361
362 _javanet_sendto (env, obj, buf, offset, len, netAddress, port);
363 if ((*env)->ExceptionOccurred (env))
364 return;
365
366 DBG ("PlainDatagramSocketImpl.sendto(): finished\n");
367 #else /* not WITHOUT_NETWORK */
368 #endif /* not WITHOUT_NETWORK */
369 }
370
371 /*************************************************************************/
372
373 /*
374 * Joins a multicast group
375 */
376 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainDatagramSocketImpl_join(JNIEnv * env,jobject obj,jobject addr)377 Java_gnu_java_net_PlainDatagramSocketImpl_join (JNIEnv * env, jobject obj,
378 jobject addr)
379 {
380 #ifndef WITHOUT_NETWORK
381 jint netAddress;
382 int fd;
383 int result;
384
385 assert (env != NULL);
386 assert ((*env) != NULL);
387
388 netAddress = _javanet_get_netaddr (env, addr);
389 if ((*env)->ExceptionOccurred (env))
390 return;
391
392 fd = _javanet_get_int_field (env, obj, "native_fd");
393 if ((*env)->ExceptionOccurred (env))
394 return;
395
396 DBG ("PlainDatagramSocketImpl.join(): have native fd\n");
397
398 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_ADD_MEMBERSHIP (fd, netAddress,
399 result);
400
401 if (result != TARGET_NATIVE_OK)
402 {
403 JCL_ThrowException (env, IO_EXCEPTION,
404 TARGET_NATIVE_LAST_ERROR_STRING ());
405 return;
406 }
407
408 DBG ("PlainDatagramSocketImpl.join(): finished\n");
409 #else /* not WITHOUT_NETWORK */
410 #endif /* not WITHOUT_NETWORK */
411 }
412
413 /*************************************************************************/
414
415 /*
416 * Leaves a multicast group
417 */
418 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainDatagramSocketImpl_leave(JNIEnv * env,jobject obj,jobject addr)419 Java_gnu_java_net_PlainDatagramSocketImpl_leave (JNIEnv * env, jobject obj,
420 jobject addr)
421 {
422 #ifndef WITHOUT_NETWORK
423 jint netAddress;
424 int fd;
425 int result;
426
427 assert (env != NULL);
428 assert ((*env) != NULL);
429
430 netAddress = _javanet_get_netaddr (env, addr);
431 if ((*env)->ExceptionOccurred (env))
432 return;
433
434 fd = _javanet_get_int_field (env, obj, "native_fd");
435 if ((*env)->ExceptionOccurred (env))
436 return;
437
438 DBG ("PlainDatagramSocketImpl.leave(): have native fd\n");
439
440 TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_DROP_MEMBERSHIP (fd, netAddress,
441 result);
442 if (result != TARGET_NATIVE_OK)
443 {
444 JCL_ThrowException (env, IO_EXCEPTION,
445 TARGET_NATIVE_LAST_ERROR_STRING ());
446 return;
447 }
448
449 DBG ("PlainDatagramSocketImpl.leave(): finished\n");
450 #else /* not WITHOUT_NETWORK */
451 #endif /* not WITHOUT_NETWORK */
452 }
453