cf99a13a98df8356fd8e6cb9236e796782aa4cb7
[cacao.git] / src / native / vm / cldc1.1 / com_sun_cldc_io_j2me_socket_Protocol.cpp
1 /* src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.cpp
2
3    Copyright (C) 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 #include "config.h"
27
28 #include <stdint.h>
29 #include <errno.h>
30 #include <netdb.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34
35 #include "vm/types.h"
36
37 #include "mm/memory.hpp"
38
39 #include "native/jni.hpp"
40 #include "native/native.hpp"
41
42 #if defined(ENABLE_JNI_HEADERS)
43 # include "native/include/com_sun_cldc_io_j2me_socket_Protocol.h"
44 #endif
45
46 #include "vm/array.hpp"
47 #include "vm/global.h"
48 #include "vm/os.hpp"
49 #include "vm/vm.hpp" /* REMOVE ME: temporarily */
50
51
52 // Native functions are exported as C functions.
53 extern "C" {
54
55 /*
56  * Class:     com/sun/cldc/io/j2me/socket/Protocol
57  * Method:    open0
58  * Signature: ([BII)I
59  */
60 JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_open0(JNIEnv *env, jclass clazz, jbyteArray hostname, jint port, jint mode)
61 {
62         struct hostent *phostent;
63     struct sockaddr_in serv_addr;
64
65         // The hostname byte-array is a NULL terminated C-string.
66         // XXX Not GC safe.
67         ByteArray ba(hostname);
68         char* name = (char*) ba.get_raw_data_ptr();
69
70         /* get the host */
71
72         phostent = gethostbyname(name);
73
74         if (phostent == NULL)
75                 return -1;
76
77         /* fill the sockaddr structure */
78
79         serv_addr.sin_family = AF_INET;
80         serv_addr.sin_port   = htons(port);
81
82         MCOPY(&serv_addr.sin_addr, phostent->h_addr, u1, phostent->h_length);
83
84         /* create the socket */
85
86         int sockfd = socket(AF_INET, SOCK_STREAM, 0);
87
88         if (sockfd < 0)
89                 return -1;
90
91         /* connect the socket */
92
93         int result = connect(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr));
94
95         if (result < 0)
96                 return -1;
97
98         return sockfd;
99 }
100
101
102 /*
103  * Class:     com/sun/cldc/io/j2me/socket/Protocol
104  * Method:    readBuf
105  * Signature: (I[BII)I
106  */
107 JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf(JNIEnv *env, jclass clazz, jint handle, jbyteArray b, jint off, jint len)
108 {
109         // Get pointer to the buffer.
110         // XXX Not GC safe.
111         ByteArray ba(b);
112         void* buf = (void*) (((int8_t*) ba.get_raw_data_ptr()) + off);
113
114         // Receive from the socket.
115         ssize_t result = recv(handle, buf, len, 0);
116
117         if (result == 0) {
118                 // The peer has performed an orderly shutdown.
119                 return -1;
120         }
121         else if (result < 0) {
122                 os::abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf: recv failed");
123         }
124
125         return result;
126 }
127
128
129 /*
130  * Class:     com/sun/cldc/io/j2me/socket/Protocol
131  * Method:    readByte
132  * Signature: (I)I
133  */
134 JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_readByte(JNIEnv *env, jclass clazz, jint handle)
135 {
136         char byte;
137         
138         // Receive from the socket.
139         ssize_t result = recv(handle, &byte, 1, 0);
140
141         if (result == 0) {
142                 // The peer has performed an orderly shutdown.
143                 return -1;
144         }
145         else if (result < 0) {
146                 // TODO Should throw an IOException.
147                 os::abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_readByte: recv failed");
148         }
149
150         return byte;
151 }
152
153
154 /*
155  * Class:     com/sun/cldc/io/j2me/socket/Protocol
156  * Method:    writeBuf
157  * Signature: (I[BII)I
158  */
159 JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf(JNIEnv *env, jclass clazz, jint handle, jbyteArray b, jint off, jint len)
160 {
161         // Get pointer to the buffer.
162         // XXX Not GC safe.
163         ByteArray ba(b);
164         void* buf = (void*) (((int8_t*) ba.get_raw_data_ptr()) + off);
165         
166         // Send the given byte to the socket.
167         ssize_t result = send(handle, buf, len, 0);
168
169         if (result < 0) {
170                 // TODO Should throw an IOException.
171                 os::abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf: send failed");
172         }
173
174         return result;
175 }
176
177
178 /*
179  * Class:     com/sun/cldc/io/j2me/socket/Protocol
180  * Method:    writeByte
181  * Signature: (II)I
182  */
183 JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte(JNIEnv *env, jclass clazz, jint handle, jint b)
184 {
185         char byte = (char) b;
186
187         // Send the given byte to the socket.
188         ssize_t result = send(handle, &byte, 1, 0);
189
190         if (result < 0)
191                 os::abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte: send failed");
192
193         return result;
194 }
195
196
197 /*
198  * Class:     com/sun/cldc/io/j2me/socket/Protocol
199  * Method:    available0
200  * Signature: (I)I
201  */
202 JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_available0(JNIEnv *env, jclass clazz, jint handle)
203 {
204         // NOTE: Sun doesn't have an implementation too.
205         return 0;
206 }
207
208
209 /*
210  * Class:     com/sun/cldc/io/j2me/socket/Protocol
211  * Method:    close0
212  * Signature: (I)V
213  */
214 JNIEXPORT void JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_close0(JNIEnv *env, jclass clazz, jint handle)
215 {
216         // Close the file descriptor.
217         int result = close(handle);
218
219         if (result < 0)
220                 os::abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_close0: close failed");
221 }
222
223 } // extern "C"
224
225
226 /* native methods implemented by this file ************************************/
227  
228 static JNINativeMethod methods[] = {
229         { (char*) "open0",      (char*) "([BII)I",  (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_open0      },
230         { (char*) "readBuf",    (char*) "(I[BII)I", (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf    },
231         { (char*) "readByte",   (char*) "(I)I",     (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_readByte   },
232         { (char*) "writeBuf",   (char*) "(I[BII)I", (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf   },
233         { (char*) "writeByte",  (char*) "(II)I",    (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte  },
234         { (char*) "available0", (char*) "(I)I",     (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_available0 },
235         { (char*) "close0",     (char*) "(I)V",     (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_close0     },
236 };
237
238  
239 /* _Jv_com_sun_cldc_io_j2me_socket_Protocol_init *******************************
240  
241    Register native functions.
242  
243 *******************************************************************************/
244  
245 void _Jv_com_sun_cldc_io_j2me_socket_Protocol_init(void)
246 {
247         utf* u = utf_new_char("com/sun/cldc/io/j2me/socket/Protocol");
248  
249         NativeMethods& nm = VM::get_current()->get_nativemethods();
250         nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
251 }
252
253
254 /*
255  * These are local overrides for various environment variables in Emacs.
256  * Please do not remove this and leave it at the end of the file, where
257  * Emacs will automagically detect them.
258  * ---------------------------------------------------------------------
259  * Local variables:
260  * mode: c++
261  * indent-tabs-mode: t
262  * c-basic-offset: 4
263  * tab-width: 4
264  * End:
265  * vim:noexpandtab:sw=4:ts=4:
266  */