35 |
obligated to do so. If you do not wish to do so, delete this |
obligated to do so. If you do not wish to do so, delete this |
36 |
exception statement from your version. */ |
exception statement from your version. */ |
37 |
|
|
38 |
#include <stdio.h> |
/* do not move; needed here because of some macro definitions */ |
39 |
#include <stdlib.h> |
#include <config.h> |
|
#include <string.h> |
|
|
#include <errno.h> |
|
|
#include <fcntl.h> |
|
|
#include <unistd.h> |
|
|
#include <sys/stat.h> |
|
40 |
|
|
41 |
|
#ifdef HAVE_MMAP |
42 |
#include <sys/mman.h> |
#include <sys/mman.h> |
43 |
#include <sys/types.h> |
#endif |
|
#include <sys/socket.h> |
|
|
#include <netinet/in.h> |
|
|
#include <netinet/tcp.h> |
|
|
#include <netinet/in.h> |
|
44 |
|
|
45 |
#include <jni.h> |
#include <jni.h> |
46 |
#include <jcl.h> |
#include <jcl.h> |
47 |
|
|
48 |
|
#include "target_native.h" |
49 |
|
#ifndef WITHOUT_NETWORK |
50 |
|
#include "target_native_network.h" |
51 |
|
#endif /* WITHOUT_NETWORK */ |
52 |
|
|
53 |
#include "gnu_java_nio_FileChannelImpl.h" |
#include "gnu_java_nio_FileChannelImpl.h" |
54 |
|
|
55 |
#include "javaio.h" |
#include "javaio.h" |
56 |
|
|
|
|
|
57 |
#define NIO_DEBUG(X) /* no debug */ |
#define NIO_DEBUG(X) /* no debug */ |
58 |
//#define NIO_DEBUG(X) X |
//#define NIO_DEBUG(X) X |
59 |
|
|
|
|
|
|
|
|
60 |
/*************************************** |
/*************************************** |
61 |
* |
* |
62 |
* File Channel implementation |
* File Channel implementation |
217 |
jint size, |
jint size, |
218 |
jint jflags) |
jint jflags) |
219 |
{ |
{ |
220 |
|
#ifdef HAVE_MMAP |
221 |
u_int64_t ret = 0; |
u_int64_t ret = 0; |
222 |
void *address; |
void *address; |
223 |
|
|
247 |
*(void **) &ret = address; |
*(void **) &ret = address; |
248 |
|
|
249 |
return ret; |
return ret; |
250 |
|
#else /* not HAVE_MMAP */ |
251 |
|
return(TARGET_NATIVE_MATH_INT_INT64_CONST_0); |
252 |
|
#endif /* not HAVE_MMAP */ |
253 |
} |
} |
254 |
|
|
255 |
|
|
257 |
jlong jaddress, |
jlong jaddress, |
258 |
int size) |
int size) |
259 |
{ |
{ |
260 |
|
#ifdef HAVE_MMAP |
261 |
int res; |
int res; |
262 |
char *address = *(void **) &jaddress; |
char *address = *(void **) &jaddress; |
263 |
|
|
269 |
{ |
{ |
270 |
perror("synchronize with file failed"); |
perror("synchronize with file failed"); |
271 |
} |
} |
272 |
|
#else /* not HAVE_MMAP */ |
273 |
|
#endif /* not HAVE_MMAP */ |
274 |
} |
} |
275 |
|
|
276 |
void nio_unmmap_file(int fd, |
void nio_unmmap_file(int fd, |
277 |
jlong jaddress, |
jlong jaddress, |
278 |
int size) |
int size) |
279 |
{ |
{ |
280 |
|
#ifdef HAVE_MMAP |
281 |
int res = 0; |
int res = 0; |
282 |
char *address = *(void **) &jaddress; |
char *address = *(void **) &jaddress; |
283 |
|
|
290 |
{ |
{ |
291 |
perror("un-mapping file failed"); |
perror("un-mapping file failed"); |
292 |
} |
} |
293 |
|
#else /* not HAVE_MMAP */ |
294 |
|
#endif /* not HAVE_MMAP */ |
295 |
} |
} |
296 |
|
|
297 |
|
|
335 |
* It's a copy to avoid a link error in orp. |
* It's a copy to avoid a link error in orp. |
336 |
*/ |
*/ |
337 |
|
|
|
#define IO_EXCEPTION "java/io/IOException" |
|
|
|
|
338 |
static |
static |
339 |
int socket_channel_get_net_addr(JNIEnv *env, jobject addr) |
int socket_channel_get_net_addr(JNIEnv *env, jobject addr) |
340 |
{ |
{ |
341 |
|
#ifndef WITHOUT_NETWORK |
342 |
jclass cls = 0; |
jclass cls = 0; |
343 |
jmethodID mid; |
jmethodID mid; |
344 |
jarray arr = 0; |
jarray arr = 0; |
350 |
/* Call the getAddress method on the object to retrieve the IP address */ |
/* Call the getAddress method on the object to retrieve the IP address */ |
351 |
cls = (*env)->GetObjectClass(env, addr); |
cls = (*env)->GetObjectClass(env, addr); |
352 |
if (cls == NULL) |
if (cls == NULL) |
353 |
return 0; |
return(0); |
354 |
|
|
355 |
mid = (*env)->GetMethodID(env, cls, "getAddress", "()[B"); |
mid = (*env)->GetMethodID(env, cls, "getAddress", "()[B"); |
356 |
if (mid == NULL) |
if (mid == NULL) |
357 |
return 0; |
return(0); |
358 |
|
|
359 |
DBG("socket_channel_get_net_addr(): Got getAddress method\n"); |
DBG("socket_channel_get_net_addr(): Got getAddress method\n"); |
360 |
|
|
361 |
arr = (*env)->CallObjectMethod(env, addr, mid); |
arr = (*env)->CallObjectMethod(env, addr, mid); |
362 |
if (arr == NULL) |
if (arr == NULL) |
363 |
return 0; |
return(0); |
364 |
|
|
365 |
DBG("socket_channel_get_net_addr(): Got the address\n"); |
DBG("socket_channel_get_net_addr(): Got the address\n"); |
366 |
|
|
368 |
len = (*env)->GetArrayLength(env, arr); |
len = (*env)->GetArrayLength(env, arr); |
369 |
if (len != 4) |
if (len != 4) |
370 |
{ |
{ |
371 |
JCL_ThrowException(env, IO_EXCEPTION, "Internal Error"); |
JCL_ThrowException(env, "java/io/IOException", "Internal Error: invalid byte array length"); |
372 |
return 0; |
return(0); |
373 |
} |
} |
374 |
DBG("socket_channel_get_net_addr(): Length ok\n"); |
DBG("socket_channel_get_net_addr(): Length ok\n"); |
375 |
|
|
376 |
octets = (*env)->GetByteArrayElements(env, arr, 0); |
octets = (*env)->GetByteArrayElements(env, arr, 0); |
377 |
if (octets == NULL) |
if (octets == NULL) |
378 |
return 0; |
return(0); |
379 |
|
|
380 |
DBG("socket_channel_get_net_addr(): Grabbed bytes\n"); |
DBG("socket_channel_get_net_addr(): Grabbed bytes\n"); |
381 |
|
|
382 |
netaddr = (((unsigned char)octets[0]) << 24) + |
TARGET_NATIVE_NETWORK_IPADDRESS_BYTES_TO_INT(octets[0], |
383 |
(((unsigned char)octets[1]) << 16) + |
octets[1], |
384 |
(((unsigned char)octets[2]) << 8) + |
octets[2], |
385 |
((unsigned char)octets[3]); |
octets[3], |
386 |
|
netaddr |
387 |
netaddr = htonl(netaddr); |
); |
388 |
|
|
389 |
(*env)->ReleaseByteArrayElements(env, arr, octets, 0); |
(*env)->ReleaseByteArrayElements(env, arr, octets, 0); |
390 |
DBG("socket_channel_get_net_addr(): Done getting addr\n"); |
DBG("socket_channel_get_net_addr(): Done getting addr\n"); |
391 |
|
|
392 |
return netaddr; |
return netaddr; |
393 |
|
#else /* not WITHOUT_NETWORK */ |
394 |
|
return(0); |
395 |
|
#endif /* not WITHOUT_NETWORK */ |
396 |
} |
} |
397 |
|
|
398 |
int Java_gnu_java_nio_SocketChannelImpl_SocketCreate(JNIEnv *env,jclass c) |
int Java_gnu_java_nio_SocketChannelImpl_SocketCreate(JNIEnv *env,jclass c) |
399 |
{ |
{ |
400 |
int val = 1; |
#ifndef WITHOUT_NETWORK |
401 |
|
int fd; |
402 |
int result; |
int result; |
403 |
|
|
404 |
result = socket(AF_INET, SOCK_STREAM, 0 /* IPPROTO_TCP */ ); |
TARGET_NATIVE_NETWORK_SOCKET_OPEN_STREAM(fd, result); |
405 |
|
if (result != TARGET_NATIVE_OK) |
406 |
// fprintf(stderr, "socket created: %d\n", result); |
{ |
407 |
|
return(0); |
408 |
|
} |
409 |
|
|
410 |
if (result < 0) return result; |
TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_REUSE_ADDRESS(fd, 1, result); |
411 |
|
if (result != TARGET_NATIVE_OK) |
412 |
setsockopt(result, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int)); |
{ |
413 |
setsockopt(result, 6 /* TCP */ , TCP_NODELAY, &val, sizeof(int)); |
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(fd,result); |
414 |
|
return(0); |
415 |
|
} |
416 |
|
TARGET_NATIVE_NETWORK_SOCKET_SET_OPTION_TCP_NODELAY(fd, 1, result); |
417 |
|
if (result != TARGET_NATIVE_OK) |
418 |
|
{ |
419 |
|
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(fd, result); |
420 |
|
return(0); |
421 |
|
} |
422 |
|
|
423 |
return result; |
return(fd); |
424 |
|
#else /* not WITHOUT_NETWORK */ |
425 |
|
return(-1); |
426 |
|
#endif /* not WITHOUT_NETWORK */ |
427 |
} |
} |
428 |
|
|
429 |
int Java_gnu_java_nio_SocketChannelImpl_SocketConnect(JNIEnv *env,jclass c,int fd, jobject InetAddress, int port) |
int Java_gnu_java_nio_SocketChannelImpl_SocketConnect(JNIEnv *env,jclass c,int fd, jobject InetAddress, int port) |
430 |
{ |
{ |
431 |
|
#ifndef WITHOUT_NETWORK |
432 |
|
int inet_addr; |
433 |
int result; |
int result; |
434 |
struct sockaddr_in server; |
int local_address; |
435 |
int inet_addr = socket_channel_get_net_addr(env, InetAddress); |
int local_port; |
436 |
|
|
437 |
server.sin_family = PF_INET; |
inet_addr = socket_channel_get_net_addr(env, InetAddress); |
438 |
server.sin_addr.s_addr = inet_addr; |
|
439 |
server.sin_port = htons(port); |
/* connect */ |
440 |
|
do |
441 |
do { |
{ |
442 |
result = connect(fd, (struct sockaddr *) &server, sizeof(server)); |
TARGET_NATIVE_NETWORK_SOCKET_CONNECT(fd, inet_addr, inet_addr, result); |
443 |
} while (result == -1 && errno == EINTR); |
} while ((result != TARGET_NATIVE_OK) && |
444 |
|
(TARGET_NATIVE_LAST_ERROR() == TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL) |
445 |
if (result >= 0) { |
); |
446 |
socklen_t len = sizeof(server); |
if (result != TARGET_NATIVE_OK) |
447 |
if (getsockname(fd, (struct sockaddr *) &server, &len) < 0) { |
{ |
448 |
|
return(-1); |
449 |
|
} |
450 |
|
|
451 |
|
/* get local address info */ |
452 |
|
TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO(fd, local_address, local_port, result); |
453 |
|
if (result != TARGET_NATIVE_OK) |
454 |
|
{ |
455 |
|
//??? NYI |
456 |
perror("getsockname: "); |
perror("getsockname: "); |
457 |
return -1; |
return(-1); |
458 |
} |
} |
459 |
result = ntohs(server.sin_port); |
|
460 |
} |
return(local_port); |
461 |
|
#else /* not WITHOUT_NETWORK */ |
462 |
return result; |
return(-1); |
463 |
|
#endif /* not WITHOUT_NETWORK */ |
464 |
} |
} |
465 |
|
|
466 |
int Java_gnu_java_nio_SocketChannelImpl_SocketBind(JNIEnv *env,jclass c,int fd, jobject InetAddress, int port) |
int Java_gnu_java_nio_SocketChannelImpl_SocketBind(JNIEnv *env,jclass c,int fd, jobject InetAddress, int port) |
467 |
{ |
{ |
468 |
struct sockaddr_in server; |
#ifndef WITHOUT_NETWORK |
469 |
int inet_addr = socket_channel_get_net_addr(env, InetAddress); |
int inet_addr; |
470 |
|
int result; |
471 |
|
int local_address; |
472 |
|
int local_port; |
473 |
|
|
474 |
server.sin_family = AF_INET; |
inet_addr = socket_channel_get_net_addr(env, InetAddress); |
475 |
server.sin_addr.s_addr = inet_addr; |
|
476 |
server.sin_port = htons(port); |
TARGET_NATIVE_NETWORK_SOCKET_BIND(fd, inet_addr, port, result); |
477 |
|
if (result != TARGET_NATIVE_OK) |
478 |
if (bind(fd, (struct sockaddr *) &server, sizeof(server)) < 0) { |
{ |
479 |
fprintf(stderr, "Error binding fd %d port %d\n", fd, port); |
//??? NYI |
480 |
perror("BIND"); |
perror("BIND"); |
|
return -1; |
|
|
} |
|
|
if (port == 0) { |
|
|
socklen_t len = sizeof(server); |
|
|
/* Find the port number and return it; */ |
|
|
if (getsockname(fd, (struct sockaddr *) &server, &len) < 0) { |
|
|
perror("getsockname: "); |
|
481 |
return -1; |
return -1; |
482 |
} |
} |
483 |
return ntohs(server.sin_port); |
if (port == 0) |
484 |
} |
{ |
485 |
return port; |
/* get local address info */ |
486 |
|
TARGET_NATIVE_NETWORK_SOCKET_GET_LOCAL_INFO(fd, local_address, local_port, result); |
487 |
|
if (result != TARGET_NATIVE_OK) |
488 |
|
{ |
489 |
|
//??? NYI |
490 |
|
perror("getsockname: "); |
491 |
|
return -1; |
492 |
|
} |
493 |
|
} |
494 |
|
else |
495 |
|
{ |
496 |
|
local_port = port; |
497 |
|
} |
498 |
|
|
499 |
|
return(local_port); |
500 |
|
#else /* not WITHOUT_NETWORK */ |
501 |
|
#endif /* not WITHOUT_NETWORK */ |
502 |
} |
} |
503 |
|
|
504 |
int Java_gnu_java_nio_SocketChannelImpl_SocketListen(JNIEnv *env,jclass c,int fd, int backlog) |
int Java_gnu_java_nio_SocketChannelImpl_SocketListen(JNIEnv *env,jclass c,int fd, int backlog) |
505 |
{ |
{ |
506 |
int res; |
#ifndef WITHOUT_NETWORK |
507 |
|
int result; |
508 |
|
|
509 |
res = listen(fd, backlog); |
TARGET_NATIVE_NETWORK_SOCKET_LISTEN(fd, backlog, result); |
510 |
|
if (result != TARGET_NATIVE_OK) |
511 |
|
{ |
512 |
|
return(-1); |
513 |
|
} |
514 |
|
|
515 |
return res; |
return(0); |
516 |
|
#else /* not WITHOUT_NETWORK */ |
517 |
|
return(-1); |
518 |
|
#endif /* not WITHOUT_NETWORK */ |
519 |
} |
} |
520 |
|
|
521 |
int Java_gnu_java_nio_SocketChannelImpl_SocketAvailable(JNIEnv *env,jclass c,int fd) |
int Java_gnu_java_nio_SocketChannelImpl_SocketAvailable(JNIEnv *env,jclass c,int fd) |
522 |
{ |
{ |
523 |
unsigned long curr = lseek(fd, 0, SEEK_CUR); |
#ifndef WITHOUT_NETWORK |
524 |
struct stat stat_buf; |
int bytes_available; |
525 |
|
int result; |
526 |
|
|
527 |
if (fstat(fd, &stat_buf) < 0) { |
TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_AVAILABLE(fd, bytes_available, result); |
528 |
return 0; |
if (result!=TARGET_NATIVE_OK) |
529 |
} |
{ |
530 |
return stat_buf.st_size - curr; |
return(0); |
531 |
|
} |
532 |
|
|
533 |
|
return(bytes_available); |
534 |
|
#else /* not WITHOUT_NETWORK */ |
535 |
|
return(0); |
536 |
|
#endif /* not WITHOUT_NETWORK */ |
537 |
} |
} |
538 |
|
|
539 |
int Java_gnu_java_nio_SocketChannelImpl_SocketClose(JNIEnv *env,jclass c,int fd) |
int Java_gnu_java_nio_SocketChannelImpl_SocketClose(JNIEnv *env,jclass c,int fd) |
540 |
{ |
{ |
541 |
if (fd >= 0) { |
#ifndef WITHOUT_NETWORK |
542 |
return close(fd); |
int result; |
|
} |
|
|
return 0; |
|
543 |
|
|
544 |
|
if (fd >= 0) { |
545 |
|
TARGET_NATIVE_NETWORK_SOCKET_CLOSE(fd, result); |
546 |
|
} |
547 |
|
|
548 |
|
return(0); |
549 |
|
#else /* not WITHOUT_NETWORK */ |
550 |
|
return(0); |
551 |
|
#endif /* not WITHOUT_NETWORK */ |
552 |
} |
} |
553 |
|
|
554 |
int Java_gnu_java_nio_SocketChannelImpl_SocketRead(JNIEnv *env,jclass c,int fd, jarray buf, int off, int len) |
int Java_gnu_java_nio_SocketChannelImpl_SocketRead(JNIEnv *env,jclass c,int fd, jarray buf, int off, int len) |
555 |
{ |
{ |
556 |
int result; |
#ifndef WITHOUT_NETWORK |
557 |
jbyte *p; |
jbyte *buffer; |
558 |
p = (*env)->GetByteArrayElements(env, buf, 0); |
int bytes_received; |
|
|
|
|
result = read(fd, p + off, len); |
|
559 |
|
|
560 |
(*env)->ReleaseByteArrayElements(env, buf, p, 0); |
buffer = (*env)->GetByteArrayElements(env, buf, 0); |
561 |
|
assert(buffer != NULL); |
562 |
|
|
563 |
// fprintf(stderr, "p=%s\n", p+off); |
TARGET_NATIVE_NETWORK_SOCKET_RECEIVE(fd, buffer + off, len, bytes_received); |
564 |
|
|
565 |
return result; |
(*env)->ReleaseByteArrayElements(env, buf, buffer, 0); |
566 |
|
|
567 |
|
return(bytes_received); |
568 |
|
#else /* not WITHOUT_NETWORK */ |
569 |
|
return(0); |
570 |
|
#endif /* not WITHOUT_NETWORK */ |
571 |
} |
} |
572 |
|
|
573 |
int Java_gnu_java_nio_SocketChannelImpl_SocketWrite(JNIEnv *env,jclass c,int fd, jarray buf, int off, int len) |
int Java_gnu_java_nio_SocketChannelImpl_SocketWrite(JNIEnv *env,jclass c,int fd, jarray buf, int off, int len) |
574 |
{ |
{ |
575 |
int result; |
#ifndef WITHOUT_NETWORK |
576 |
jbyte *p; |
jbyte *buffer; |
577 |
p = (*env)->GetByteArrayElements(env, buf, 0); |
int bytes_sent; |
578 |
|
|
579 |
result = write(fd, p + off, len); |
buffer = (*env)->GetByteArrayElements(env, buf, 0); |
580 |
|
|
581 |
(*env)->ReleaseByteArrayElements(env, buf, p, 0); |
TARGET_NATIVE_NETWORK_SOCKET_SEND(fd, buffer + off, len, bytes_sent); |
582 |
|
|
583 |
|
(*env)->ReleaseByteArrayElements(env, buf, buffer, 0); |
584 |
|
|
585 |
return result; |
return(bytes_sent); |
586 |
|
#else /* not WITHOUT_NETWORK */ |
587 |
|
return(0); |
588 |
|
#endif /* not WITHOUT_NETWORK */ |
589 |
} |
} |