1 /* PlainSocketImpl.c - Native methods for PlainSocketImpl class
2    Copyright (C) 1998, 2002, 2005  Free Software Foundation, Inc.
3 
4    Modifications are copyright (C) 2004 by Etienne M. Gagnon
5    <gagnon.etienne_m@uqam.ca>.  All rights reserved.
6 
7 This file is part of GNU Classpath.
8 
9 GNU Classpath is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13 
14 GNU Classpath is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with GNU Classpath; see the file COPYING.  If not, write to the
21 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 02110-1301 USA.
23 
24 Linking this library statically or dynamically with other modules is
25 making a combined work based on this library.  Thus, the terms and
26 conditions of the GNU General Public License cover the whole
27 combination.
28 
29 As a special exception, the copyright holders of this library give you
30 permission to link this library with independent modules to produce an
31 executable, regardless of the license terms of these independent
32 modules, and to copy and distribute the resulting executable under
33 terms of your choice, provided that you also meet, for each linked
34 independent module, the terms and conditions of the license of that
35 module.  An independent module is a module which is not derived from
36 or based on this library.  If you modify this library, you may extend
37 this exception to your version of the library, but you are not
38 obligated to do so.  If you do not wish to do so, delete this
39 exception statement from your version. */
40 
41 /* do not move; needed here because of some macro definitions */
42 #include <config.h>
43 
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <assert.h>
48 
49 #include <jni.h>
50 #include <jcl.h>
51 
52 #include "javanet.h"
53 
54 #include "target_native.h"
55 #ifndef WITHOUT_NETWORK
56 #include "target_native_file.h"  /* Get FIONREAD on Solaris.  */
57 #include "target_native_network.h"
58 #endif /* WITHOUT_NETWORK */
59 
60 #include "gnu_java_net_PlainSocketImpl.h"
61 
62 /*
63  * Note that the functions in this module simply redirect to another
64  * internal function.  Why?  Because many of these functions are shared
65  * with PlainDatagramSocketImpl.  The unshared ones were done the same
66  * way for consistency.
67  */
68 
69 /*************************************************************************/
70 
71 /*
72  * Creates a new stream or datagram socket
73  */
74 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainSocketImpl_create(JNIEnv * env,jobject this,jboolean stream)75 Java_gnu_java_net_PlainSocketImpl_create (JNIEnv * env, jobject this,
76 					  jboolean stream)
77 {
78 #ifndef WITHOUT_NETWORK
79   assert (env != NULL);
80   assert ((*env) != NULL);
81 
82   _javanet_create (env, this, stream);
83 #else /* not WITHOUT_NETWORK */
84 #endif /* not WITHOUT_NETWORK */
85 }
86 
87 /*************************************************************************/
88 
89 /*
90  * Close the socket.  Any underlying streams will be closed by this
91  * action as well.
92  */
93 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainSocketImpl_close(JNIEnv * env,jobject this)94 Java_gnu_java_net_PlainSocketImpl_close (JNIEnv * env, jobject this)
95 {
96 #ifndef WITHOUT_NETWORK
97   assert (env != NULL);
98   assert ((*env) != NULL);
99 
100   _javanet_close (env, this, 1);
101 #else /* not WITHOUT_NETWORK */
102 #endif /* not WITHOUT_NETWORK */
103 }
104 
105 /*************************************************************************/
106 
107 /*
108  * Connects to the specified destination.
109  */
110 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainSocketImpl_connect(JNIEnv * env,jobject this,jobject addr,jint port)111 Java_gnu_java_net_PlainSocketImpl_connect (JNIEnv * env, jobject this,
112 					   jobject addr, jint port)
113 {
114 #ifndef WITHOUT_NETWORK
115   assert (env != NULL);
116   assert ((*env) != NULL);
117 
118   _javanet_connect (env, this, addr, port);
119 #else /* not WITHOUT_NETWORK */
120 #endif /* not WITHOUT_NETWORK */
121 }
122 
123 /*************************************************************************/
124 
125 /*
126  * This method binds the specified address to the specified local port.
127  * Note that we have to set the local address and local port public instance
128  * variables.
129  */
130 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainSocketImpl_bind(JNIEnv * env,jobject this,jobject addr,jint port)131 Java_gnu_java_net_PlainSocketImpl_bind (JNIEnv * env, jobject this,
132 					jobject addr, jint port)
133 {
134 #ifndef WITHOUT_NETWORK
135   assert (env != NULL);
136   assert ((*env) != NULL);
137 
138   _javanet_bind (env, this, addr, port, 1);
139 #else /* not WITHOUT_NETWORK */
140 #endif /* not WITHOUT_NETWORK */
141 }
142 
143 /*************************************************************************/
144 
145 /*
146  * Starts listening on a socket with the specified number of pending
147  * connections allowed.
148  */
149 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainSocketImpl_listen(JNIEnv * env,jobject this,jint queuelen)150 Java_gnu_java_net_PlainSocketImpl_listen (JNIEnv * env, jobject this,
151 					  jint queuelen)
152 {
153 #ifndef WITHOUT_NETWORK
154   assert (env != NULL);
155   assert ((*env) != NULL);
156 
157   _javanet_listen (env, this, queuelen);
158 #else /* not WITHOUT_NETWORK */
159 #endif /* not WITHOUT_NETWORK */
160 }
161 
162 /*************************************************************************/
163 
164 /*
165  * Accepts a new connection and assigns it to the passed in SocketImpl
166  * object. Note that we assume this is a PlainSocketImpl just like us.
167  */
168 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainSocketImpl_accept(JNIEnv * env,jobject this,jobject impl)169 Java_gnu_java_net_PlainSocketImpl_accept (JNIEnv * env, jobject this,
170 					  jobject impl)
171 {
172 #ifndef WITHOUT_NETWORK
173   assert (env != NULL);
174   assert ((*env) != NULL);
175 
176   _javanet_accept (env, this, impl);
177 #else /* not WITHOUT_NETWORK */
178 #endif /* not WITHOUT_NETWORK */
179 }
180 
181 /*************************************************************************/
182 
183 JNIEXPORT jint JNICALL
Java_gnu_java_net_PlainSocketImpl_available(JNIEnv * env,jobject this)184 Java_gnu_java_net_PlainSocketImpl_available (JNIEnv * env, jobject this)
185 {
186 #ifndef WITHOUT_NETWORK
187   jclass cls;
188   jfieldID fid;
189   int fd;
190   int bytesAvailable;
191   int result;
192 
193   assert (env != NULL);
194   assert ((*env) != NULL);
195 
196   cls = (*env)->GetObjectClass (env, this);
197   if (cls == 0)
198     {
199       JCL_ThrowException (env, IO_EXCEPTION, "internal error");
200       return 0;
201     }
202 
203   fid = (*env)->GetFieldID (env, cls, "native_fd", "I");
204   if (fid == 0)
205     {
206       JCL_ThrowException (env, IO_EXCEPTION, "internal error");
207       return 0;
208     }
209 
210   fd = (*env)->GetIntField (env, this, fid);
211 
212   TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_AVAILABLE (fd, bytesAvailable, result);
213   if (result != TARGET_NATIVE_OK)
214     {
215       JCL_ThrowException (env, IO_EXCEPTION,
216 			  TARGET_NATIVE_LAST_ERROR_STRING ());
217       return 0;
218     }
219 
220   return bytesAvailable;
221 #else /* not WITHOUT_NETWORK */
222   return 0;
223 #endif /* not WITHOUT_NETWORK */
224 }
225 
226 /*************************************************************************/
227 
228 /*
229  * This method sets the specified option for a socket
230  */
231 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainSocketImpl_setOption(JNIEnv * env,jobject this,jint option_id,jobject val)232 Java_gnu_java_net_PlainSocketImpl_setOption (JNIEnv * env, jobject this,
233 					     jint option_id, jobject val)
234 {
235 #ifndef WITHOUT_NETWORK
236   assert (env != NULL);
237   assert ((*env) != NULL);
238 
239   _javanet_set_option (env, this, option_id, val);
240 #else /* not WITHOUT_NETWORK */
241 #endif /* not WITHOUT_NETWORK */
242 }
243 
244 /*************************************************************************/
245 
246 /*
247  * This method sets the specified option for a socket
248  */
249 JNIEXPORT jobject JNICALL
Java_gnu_java_net_PlainSocketImpl_getOption(JNIEnv * env,jobject this,jint option_id)250 Java_gnu_java_net_PlainSocketImpl_getOption (JNIEnv * env, jobject this,
251 					     jint option_id)
252 {
253 #ifndef WITHOUT_NETWORK
254   assert (env != NULL);
255   assert ((*env) != NULL);
256 
257   return (_javanet_get_option (env, this, option_id));
258 #else /* not WITHOUT_NETWORK */
259   return NULL;
260 #endif /* not WITHOUT_NETWORK */
261 }
262 
263 /*************************************************************************/
264 
265 /*
266  * Reads a buffer from a remote host
267  */
268 JNIEXPORT jint JNICALL
Java_gnu_java_net_PlainSocketImpl_read(JNIEnv * env,jobject this,jarray buf,jint offset,jint len)269 Java_gnu_java_net_PlainSocketImpl_read (JNIEnv * env, jobject this,
270 					jarray buf, jint offset, jint len)
271 {
272 #ifndef WITHOUT_NETWORK
273   assert (env != NULL);
274   assert ((*env) != NULL);
275 
276   return (_javanet_recvfrom (env, this, buf, offset, len, 0, 0));
277 #else /* not WITHOUT_NETWORK */
278   return 0;
279 #endif /* not WITHOUT_NETWORK */
280 }
281 
282 /*************************************************************************/
283 
284 /*
285  * Reads a char from a remote host
286  */
287 JNIEXPORT jint JNICALL
Java_gnu_java_net_PlainSocketImpl_nativeRead(JNIEnv * env,jclass class,jint fd)288 Java_gnu_java_net_PlainSocketImpl_nativeRead (JNIEnv *env, jclass class, jint fd)
289 {
290 #ifndef WITHOUT_NETWORK
291 
292   jbyte b;
293   size_t recv_count;
294 
295   /* receive one char */
296   recv_count = recv (fd, &b, 1, 0);
297 
298   /* error, throw IOException */
299   if (recv_count == -1)
300     {
301       JCL_ThrowException(env, IO_EXCEPTION, strerror(errno));
302       return -1;
303     }
304 
305   /* EOF: it's a blocking call, so it shouldn't return 0 unless EOF is
306      reached */
307   if (recv_count == 0)
308     {
309       return -1;
310     }
311 
312   assert (recv_count == 1);
313 
314   return ((jint) b) & 0x000000FF;
315 
316 #else /* not WITHOUT_NETWORK */
317 #endif /* not WITHOUT_NETWORK */
318 }
319 
320 /*************************************************************************/
321 
322 /*
323  * Writes a buffer to the remote host
324  */
325 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainSocketImpl_write(JNIEnv * env,jobject this,jarray buf,jint offset,jint len)326 Java_gnu_java_net_PlainSocketImpl_write (JNIEnv * env, jobject this,
327 					 jarray buf, jint offset, jint len)
328 {
329 #ifndef WITHOUT_NETWORK
330   assert (env != NULL);
331   assert ((*env) != NULL);
332 
333   _javanet_sendto (env, this, buf, offset, len, 0, 0);
334 #else /* not WITHOUT_NETWORK */
335 #endif /* not WITHOUT_NETWORK */
336 }
337 
338 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainSocketImpl_shutdownInput(JNIEnv * env,jobject this)339 Java_gnu_java_net_PlainSocketImpl_shutdownInput (JNIEnv * env, jobject this)
340 {
341 #ifndef WITHOUT_NETWORK
342   assert (env != NULL);
343   assert ((*env) != NULL);
344 
345   _javanet_shutdownInput (env, this);
346 #else /* not WITHOUT_NETWORK */
347 #endif /* not WITHOUT_NETWORK */
348 }
349 
350 JNIEXPORT void JNICALL
Java_gnu_java_net_PlainSocketImpl_shutdownOutput(JNIEnv * env,jobject this)351 Java_gnu_java_net_PlainSocketImpl_shutdownOutput (JNIEnv * env, jobject this)
352 {
353 #ifndef WITHOUT_NETWORK
354   assert (env != NULL);
355   assert ((*env) != NULL);
356 
357   _javanet_shutdownOutput (env, this);
358 #else /* not WITHOUT_NETWORK */
359 #endif /* not WITHOUT_NETWORK */
360 }
361 
362 /* end of file */
363