📄 nbio.c
字号:
memset((char *)&him, 0, sizeof(him)); him.sin_port = htons((short)port); him.sin_addr.s_addr = (unsigned long)htonl(inet_address); him.sin_family = inet_family; if ((ret = bind(fd, (struct sockaddr *)&him, sizeof(him))) < 0) { if (errno == EACCES) { THROW_EXCEPTION(env, "java/net/BindException", strerror(errno)); } else { THROW_EXCEPTION(env, "java/net/SocketException", strerror(errno)); } return; } cls = (*env)->GetObjectClass(env, this); fid = (*env)->GetFieldID(env, cls, "address", "Ljava/net/InetAddress;"); (*env)->SetObjectField(env, this, fid, address); fid = (*env)->GetFieldID(env, cls, "port", "I"); (*env)->SetIntField(env, this, fid, port); fid = (*env)->GetFieldID(env, cls, "localport", "I"); /* Set local port value */ if (port == 0) { /* Set localport value -- may have been previously set by bind operation */ int len = sizeof(him); if (getsockname(fd,(struct sockaddr *)&him, &len) == -1) { THROW_EXCEPTION(env, "java/net/SocketException", strerror(errno)); return; } (*env)->SetIntField(env, this, fid, ntohs(him.sin_port)); } else { (*env)->SetIntField(env, this, fid, port); } return;} /* * Class: ninja2_core_io_0005fcore_nbio_NonblockingSocketImpl * Method: nbSocketListen * Signature: (I)V */JNIEXPORT void JNICALL Java_ninja2_core_io_1core_nbio_NonblockingSocketImpl_nbSocketListen (JNIEnv *env, jobject this, jint count) { int fd; jclass cls = (*env)->GetObjectClass(env, this); jfieldID fid = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;"); jobject fdobj = (*env)->GetObjectField(env, this, fid); if (fdobj == NULL) { THROW_EXCEPTION(env, "java/net/SocketException", "socket closed"); return; } cls = (*env)->GetObjectClass(env, fdobj); fid = (*env)->GetFieldID(env, cls, "fd", "I"); fd = (*env)->GetIntField(env, fdobj, fid); if (fd == -1) { THROW_EXCEPTION(env, "java/net/SocketException", "socket closed"); return; } if (listen(fd, count) < 0) { THROW_EXCEPTION(env, "java/net/SocketException", strerror(errno)); return; }}/* * Class: ninja2_core_io_0005fcore_nbio_NonblockingSocketImpl * Method: nbSocketAccept * Signature: (Lninja2/core/io_core/nbio/NonblockingSocketImpl;)V */JNIEXPORT jint JNICALL Java_ninja2_core_io_1core_nbio_NonblockingSocketImpl_nbSocketAccept (JNIEnv *env, jobject this, jobject newsocket, jboolean block) { int fd, newfd; struct sockaddr_in him; int len, localport; jobject sptr_inetaddr, sptr_fdobj; jclass cls = (*env)->GetObjectClass(env, this); jfieldID fid = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;"); jobject fdobj = (*env)->GetObjectField(env, this, fid); if (fdobj == NULL) { THROW_EXCEPTION(env, "java/net/SocketException", "socket closed"); return -1; } cls = (*env)->GetObjectClass(env, fdobj); fid = (*env)->GetFieldID(env, cls, "fd", "I"); fd = (*env)->GetIntField(env, fdobj, fid); if (fd == -1) { THROW_EXCEPTION(env, "java/net/SocketException", "socket closed"); return -1; } if (newsocket == NULL) { THROW_EXCEPTION(env, "java/lang/NullPointerException", "newsocket is NULL"); return -1; } /* We expect that the 'fd' field of the newsocket has * been created outside of this method (but not initialized). */ cls = (*env)->GetObjectClass(env, newsocket); fid = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;"); sptr_fdobj = (*env)->GetObjectField(env, newsocket, fid); if (sptr_fdobj == NULL) { THROW_EXCEPTION(env, "java/lang/NullPointerException", "newsocket uninitialized"); return -1; } /* XXX MDW This is not threadsafe */ if (!block) { nbio_make_nonblocking(env, fd); } else { nbio_make_blocking(env, fd); } DEBUG(fprintf(stderr,"NBIO: Doing accept() on fd=%d\n", fd));#ifdef linux len = sizeof(him);#endif #ifdef SOLARIS len = sizeof(struct sockaddr); #endif newfd = nbio_real_accept(fd, (struct sockaddr *)&him, &len); if (newfd < 0) { if (!block && errno == EWOULDBLOCK) return -1; else { THROW_EXCEPTION(env, "java/net/SocketException", strerror(errno)); return -1; } } nbio_make_nonblocking(env, newfd); nbio_disable_nagle(env, newfd); cls = (*env)->GetObjectClass(env, sptr_fdobj); fid = (*env)->GetFieldID(env, cls, "fd", "I"); // fd == -1 indicates not initialized (*env)->SetIntField(env, sptr_fdobj, fid, newfd); cls = (*env)->GetObjectClass(env, this); fid = (*env)->GetFieldID(env, cls, "localport", "I"); localport = (*env)->GetIntField(env, this, fid); /* Create empty InetAddress and initialize it */ DEBUG(fprintf(stderr,"NBIO: accept() creating new InetAddress\n")); cls = (*env)->FindClass(env, "java/net/InetAddress"); if (cls == NULL) { THROW_EXCEPTION(env, "java/net/SocketException", "Cannot find java.net.InetAddress class"); return -1; } sptr_inetaddr = (*env)->AllocObject(env, cls); DEBUG(fprintf(stderr,"NBIO: accept() initializing new InetAddress\n")); fid = (*env)->GetFieldID(env, cls, "address", "I"); (*env)->SetIntField(env, sptr_inetaddr, fid, ntohl(him.sin_addr.s_addr)); fid = (*env)->GetFieldID(env, cls, "family", "I"); (*env)->SetIntField(env, sptr_inetaddr, fid, him.sin_family); cls = (*env)->GetObjectClass(env, newsocket); fid = (*env)->GetFieldID(env, cls, "port", "I"); (*env)->SetIntField(env, newsocket, fid, ntohs(him.sin_port)); fid = (*env)->GetFieldID(env, cls, "localport", "I"); (*env)->SetIntField(env, newsocket, fid, localport); fid = (*env)->GetFieldID(env, cls, "address", "Ljava/net/InetAddress;"); (*env)->SetObjectField(env, newsocket, fid, sptr_inetaddr); return 0;}/* * Class: ninja2_core_io_0005fcore_nbio_NonblockingSocketImpl * Method: nbSocketAvailable * Signature: ()I */JNIEXPORT jint JNICALL Java_ninja2_core_io_1core_nbio_NonblockingSocketImpl_nbSocketAvailable (JNIEnv *env, jobject this) { int fd; int bytes; jclass cls = (*env)->GetObjectClass(env, this); jfieldID fid = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;"); jobject fdobj = (*env)->GetObjectField(env, this, fid); if (fdobj == NULL) { THROW_EXCEPTION(env, "java/net/SocketException", "socket closed"); return; } cls = (*env)->GetObjectClass(env, fdobj); fid = (*env)->GetFieldID(env, cls, "fd", "I"); fd = (*env)->GetIntField(env, fdobj, fid); if (fd == -1) { THROW_EXCEPTION(env, "java/net/SocketException", "socket closed"); return; }#ifdef linux if (ioctl(fd, FIONREAD, &bytes) < 0) {#endif /* linux */#ifdef SOLARIS if (ioctl(fd, I_NREAD, &bytes) < 0) {#endif /* SOLARIS */ THROW_EXCEPTION(env, "java/net/SocketException", strerror(errno)); return; } DEBUG(fprintf(stderr,"NBIO: nbSocketAvailable called, %d bytes available\n", bytes)); return bytes;}/* * Class: ninja2_core_io_0005fcore_nbio_NonblockingSocketImpl * Method: nbSocketClose * Signature: ()V */JNIEXPORT void JNICALL Java_ninja2_core_io_1core_nbio_NonblockingSocketImpl_nbSocketClose (JNIEnv * env, jobject this) { int fd; jclass cls = (*env)->GetObjectClass(env, this); jfieldID fid = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;"); jobject fdobj = (*env)->GetObjectField(env, this, fid); if (fdobj == NULL) { //THROW_EXCEPTION(env, "java/net/SocketException", "socket closed"); return; } cls = (*env)->GetObjectClass(env, fdobj); fid = (*env)->GetFieldID(env, cls, "fd", "I"); fd = (*env)->GetIntField(env, fdobj, fid); if (fd == -1) { //THROW_EXCEPTION(env, "java/net/SocketException", "socket closed"); return; } close(fd); (*env)->SetIntField(env, fdobj, fid, 0);}/* NonblockingSocketInputStream *******************************************//* * Class: ninja2_core_io_0005fcore_nbio_NonblockingSocketInputStream * Method: nbSocketRead * Signature: ([BII)I */JNIEXPORT jint JNICALL Java_ninja2_core_io_1core_nbio_NonblockingSocketInputStream_nbSocketRead (JNIEnv *env, jobject this, jbyteArray b, jint off, jint len) { int fd; jclass cls; jfieldID fid; jobject fdobj; int datalen; char *data; int n; DEBUG(fprintf(stderr,"NBIO: nbSocketRead called, off=%d len=%d\n", off, len)); cls = (*env)->GetObjectClass(env, this); fid = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;"); fdobj = (*env)->GetObjectField(env, this, fid); if (fdobj == NULL) { THROW_EXCEPTION(env, "java/net/SocketException", "socket closed"); return; } cls = (*env)->GetObjectClass(env, fdobj); fid = (*env)->GetFieldID(env, cls, "fd", "I"); fd = (*env)->GetIntField(env, fdobj, fid); if (fd == -1) { THROW_EXCEPTION(env, "java/net/SocketException", "socket closed"); return; } if (b == NULL) { THROW_EXCEPTION(env, "java/lang/NullPointerException", "null byte array passed to nbSocketRead"); return; } datalen = (*env)->GetArrayLength(env, b); if (len < 0 || len + off > datalen) { THROW_EXCEPTION(env, "java/lang/ArrayIndexOutOfBoundsException", "len must be >= 0 and len + off <= array length"); } data = (*env)->GetByteArrayElements(env, b, NULL); n = nbio_real_read(fd, data+off, len); DEBUG(fprintf(stderr,"NBIO: nbSocketRead: off is %d, len is %d, got %d, errno is %d\n", off, len, n, errno)); if (n == 0) { // Socket was closed (*env)->ReleaseByteArrayElements(env, b, data, JNI_ABORT); return -1; // EOF } else if (n < 0) { if (errno == EAGAIN) { (*env)->ReleaseByteArrayElements(env, b, data, JNI_ABORT); return 0; // No data returned } else { THROW_EXCEPTION(env, "java/net/SocketException", strerror(errno)); (*env)->ReleaseByteArrayElements(env, b, data, JNI_ABORT); return -1; // error } } (*env)->ReleaseByteArrayElements(env, b, data, 0); return n;}/* * Class: ninja2_core_io_0005fcore_nbio_NonblockingSocketOutputStream * Method: nbSocketWrite * Signature: ([BII)I */JNIEXPORT jint JNICALL Java_ninja2_core_io_1core_nbio_NonblockingSocketOutputStream_nbSocketWrite (JNIEnv *env, jobject this, jbyteArray b, jint off, jint len) { int fd; jclass cls; jfieldID fid; jobject fdobj; int datalen; char *data; int n; DEBUG(fprintf(stderr,"NBIO: nbSocketWrite called, off=%d len=%d\n", off, len)); cls = (*env)->GetObjectClass(env, this); fid = (*env)->GetFieldID(env, cls, "fd", "Lninja2/core/io_core/nbio/NBIOFileDescriptor;"); fdobj = (*env)->GetObjectField(env, this, fid); if (fdobj == NULL) { THROW_EXCEPTION(env, "java/net/SocketException", "socket closed"); return; } cls = (*env)->GetObjectClass(env, fdobj); fid = (*env)->GetFieldID(env, cls, "fd", "I"); fd = (*env)->GetIntField(env, fdobj, fid); if (fd == -1) { THROW_EXCEPTION(env, "java/net/SocketException", "socket closed"); return; } if (b == NULL) { THROW_EXCEPTION(env, "java/lang/NullPointerException", "null byte array passed to nbSocketWrite"); return; } datalen = (*env)->GetArrayLength(env, b); if (len < 0 || len + off > datalen) { THROW_EXCEPTION(env, "java/lang/ArrayIndexOutOfBoundsException", "len must be >= 0 and len + off <= array length"); } data = (*env)->GetByteArrayElements(env, b, NULL); n = nbio_real_write(fd, data+off, len); DEBUG(fprintf(stderr,"NBIO: nbSocketWrite: off is %d, len is %d, got %d, errno is %d\n", off, len, n, errno)); if (n < 0) { if (errno == EAGAIN) { (*env)->ReleaseByteArrayElements(env, b, data, JNI_ABORT); return 0; // No data returned } else { THROW_EXCEPTION(env, "java/net/SocketException", strerror(errno)); (*env)->ReleaseByteArrayElements(env, b, data, JNI_ABORT); return -1; // error } } (*env)->ReleaseByteArrayElements(env, b, data, JNI_ABORT); return n;}/* SelectSetDevPollImpl ******************************************************/#ifndef HAS_DEVPOLLJNIEXPORT jboolean JNICALL Java_ninja2_core_io_1core_nbio_SelectSetDevPollImpl_supported(JNIEnv *env, jclass cls) { /* Safe setting when compiling on systems where /dev/poll not available */ return JNI_FALSE;}#else /* HAS_DEVPOLL *//* Define to use B-Tree to map fd to selitemobj#undef USE_BTREE /* Max number of file descriptors if flat table used */#define MAX_FDS 4096typedef struct devpoll_impl_state { int devpoll_fd; int max_retevents; struct pollfd *retevents;#ifdef USE_BTREE btree_node *tree;#else jobject selitems[MAX_FDS];#endif} devpoll_impl_state;JNIEXPORT jboolean JNICALL Java_ninja2_core_io_1core_nbio_SelectSetDevPollImpl_supported(JNIEnv *env, jclass cls) { struct stat statbuf; /* If we were compiled on a system with /dev/poll, but running where * it's not available, return false */ if (stat("/dev/poll", &statbuf) == 0) { return JNI_TRUE; } else { return JNI_FALSE; }}JNIEXPORT void JNICALL Java_ninja2_core_io_1core_nbio_SelectSetDevPollImpl_init (JNIEnv * env, jobject this, jint max_retevents) { jclass cls; jfieldID fid; devpoll_impl_state *state; int i; DEBUG(fprintf(stderr,"SelectSetDevPollImpl.init(%d) called\n", max_retevents)); // Allocate state state = (devpoll_impl_state *)malloc(sizeof(devpoll_impl_state)); if (state == NULL) { THROW_EXCEPTION(env, "java/lang/OutOfMemoryError", "Cannot allocate devpoll_impl_state"); return; } // Set state field cls = (*env)->GetObjectClass(env, this); fid = (*env)->GetFieldID(env, cls, "native_state", "J"); (*env)->SetLongField(env, this, fid, (jlong)state); DEBUG(fprintf(stderr,"SelectSetDevPollImpl.init set state field\n")); state->max_retevents = max_retevents; state->devpoll_fd = open("/dev/poll", O_RDWR); if (state->devpoll_fd < 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -