jobject recvFrom0(JNIEnv * env, jint fd, void* buffer, jint pos, jint limit) { struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); ssize_t res; int err; do { res = recvfrom(fd, buffer + pos, (size_t) (limit - pos), 0, (struct sockaddr *)&addr, &addrlen); // Keep on reading if we was interrupted } while (res == -1 && ((err = errno) == EINTR)); if (res < 0) { if (err == EAGAIN || err == EWOULDBLOCK) { // Nothing left to read return NULL; } if (err == EBADF) { throwClosedChannelException(env); return NULL; } throwIOException(env, exceptionMessage("Error while recvFrom(...): ", err)); return NULL; } return createDatagramSocketAddress(env, addr, res); }
jint sendTo0(JNIEnv * env, jint fd, void* buffer, jint pos, jint limit ,jbyteArray address, jint scopeId, jint port) { struct sockaddr_storage addr; init_sockaddr(env, address, scopeId, port, &addr); ssize_t res; int err; do { res = sendto(fd, buffer + pos, (size_t) (limit - pos), 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_storage)); // keep on writing if it was interrupted } while(res == -1 && ((err = errno) == EINTR)); if (res < 0) { // network stack saturated... try again later if (err == EAGAIN || err == EWOULDBLOCK) { return 0; } if (err == EBADF) { throwClosedChannelException(env); return -1; } throwIOException(env, exceptionMessage("Error while sendto(...): ", err)); return -1; } return (jint) res; }
jint epollCtl(JNIEnv * env, jint efd, int op, jint fd, jint flags, jint id) { uint32_t events = EPOLLET; if (flags & EPOLL_ACCEPT) { events |= EPOLLIN; } if (flags & EPOLL_READ) { events |= EPOLLIN | EPOLLRDHUP; } if (flags & EPOLL_WRITE) { events |= EPOLLOUT; } struct epoll_event ev = { .events = events, // encode the id into the events .data.u64 = (((uint64_t) id) << 32L) }; return epoll_ctl(efd, op, fd, &ev); } jint getOption(JNIEnv *env, jint fd, int level, int optname, const void *optval, socklen_t optlen) { int code; code = getsockopt(fd, level, optname, optval, &optlen); if (code == 0) { return 0; } int err = errno; throwRuntimeException(env, exceptionMessage("Error during getsockopt(...): ", err)); return code; }
jint read0(JNIEnv * env, jclass clazz, jint fd, void *buffer, jint pos, jint limit) { ssize_t res; int err; do { res = read(fd, buffer + pos, (size_t) (limit - pos)); // Keep on reading if we was interrupted } while (res == -1 && ((err = errno) == EINTR)); if (res < 0) { if (err == EAGAIN || err == EWOULDBLOCK) { // Nothing left to read return 0; } if (err == EBADF) { throwClosedChannelException(env); return -1; } throwIOException(env, exceptionMessage("Error while read(...): ", err)); return -1; } if (res == 0) { // end-of-stream return -1; } return (jint) res; }
int setOption(JNIEnv *env, jint fd, int level, int optname, const void *optval, socklen_t len) { int rc = setsockopt(fd, level, optname, optval, len); if (rc < 0) { int err = errno; throwRuntimeException(env, exceptionMessage("Error during setsockopt(...): ", err)); } return rc; }
JNIEXPORT void JNICALL Java_io_netty_channel_epoll_Native_epollCtlDel(JNIEnv * env, jclass clazz, jint efd, jint fd) { // Create an empty event to workaround a bug in older kernels which can not handle NULL. struct epoll_event event = { 0 }; if (epoll_ctl(efd, EPOLL_CTL_DEL, fd, &event) < 0) { int err = errno; throwRuntimeException(env, exceptionMessage("Error during calling epoll_ctl(...): ", err)); } }
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_epollCreate(JNIEnv * env, jclass clazz) { jint efd = epoll_create1(EPOLL_CLOEXEC); if (efd < 0) { int err = errno; throwRuntimeException(env, exceptionMessage("Error during epoll_create(...): ", err)); } return efd; }
JNIEXPORT void JNICALL Java_io_netty_channel_epoll_Native_eventFdWrite(JNIEnv * env, jclass clazz, jint fd, jlong value) { jint eventFD = eventfd_write(fd, (eventfd_t)value); if (eventFD < 0) { int err = errno; throwRuntimeException(env, exceptionMessage("Error calling eventfd_write(...): ", err)); } }
JNIEXPORT void JNICALL Java_io_netty_channel_epoll_Native_bind(JNIEnv * env, jclass clazz, jint fd, jbyteArray address, jint scopeId, jint port) { struct sockaddr_storage addr; init_sockaddr(env, address, scopeId, port, &addr); if(bind(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1){ int err = errno; throwIOException(env, exceptionMessage("Error during bind(...): ", err)); } }
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_eventFd(JNIEnv * env, jclass clazz) { jint eventFD = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); if (eventFD < 0) { int err = errno; throwRuntimeException(env, exceptionMessage("Error creating eventFD(...): ", err)); } return eventFD; }
void FileDAO::closeInputter(){ if(inputStream_.is_open()) { inputStream_.close(); } else { std::string exceptionMessage("File Handler is already closed."); throw exceptionMessage; } }
JNIEXPORT jstring JNICALL Java_io_netty_channel_epoll_Native_kernelVersion(JNIEnv *env, jclass clazz) { struct utsname name; int res = uname(&name); if (res == 0) { return (*env)->NewStringUTF(env, name.release); } int err = errno; throwRuntimeException(env, exceptionMessage("Error during uname(...): ", err)); return NULL; }
std::string FileDAO::readData(){ if(inputStream_.is_open()) { std::string readData; getline(inputStream_, readData); return readData; } else { std::string exceptionMessage("File is not opened."); throw exceptionMessage; return ""; } }
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_epollWait(JNIEnv * env, jclass clazz, jint efd, jlongArray events, jint timeout) { int len = (*env)->GetArrayLength(env, events); struct epoll_event ev[len]; int ready; int err; do { ready = epoll_wait(efd, ev, len, timeout); // was interrupted try again. } while (ready == -1 && (( err = errno) == EINTR)); if (ready < 0) { throwIOException(env, exceptionMessage("Error during epoll_wait(...): ", err)); return -1; } if (ready == 0) { // nothing ready for process return 0; } jboolean isCopy; jlong *elements = (*env)->GetLongArrayElements(env, events, &isCopy); if (elements == NULL) { // No memory left ?!?!? throwOutOfMemoryError(env, "Can't allocate memory"); return -1; } int i; for (i = 0; i < ready; i++) { // store the ready ops and id elements[i] = (jlong) ev[i].data.u64; if (ev[i].events & EPOLLIN) { elements[i] |= EPOLL_READ; } if (ev[i].events & EPOLLRDHUP) { elements[i] |= EPOLL_RDHUP; } if (ev[i].events & EPOLLOUT) { elements[i] |= EPOLL_WRITE; } } jint mode; // release again to prevent memory leak if (isCopy) { mode = 0; } else { // was just pinned so use JNI_ABORT to eliminate not needed copy. mode = JNI_ABORT; } (*env)->ReleaseLongArrayElements(env, events, elements, mode); return ready; }
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_epollCreate(JNIEnv * env, jclass clazz) { jint efd; if (epoll_create1) { efd = epoll_create1(EPOLL_CLOEXEC); } else { // size will be ignored anyway but must be positive efd = epoll_create(126); } if (efd < 0) { int err = errno; throwRuntimeException(env, exceptionMessage("Error during epoll_create(...): ", err)); } if (!epoll_create1) { if (fcntl(efd, F_SETFD, FD_CLOEXEC) < 0) { int err = errno; close(efd); throwRuntimeException(env, exceptionMessage("Error during fcntl(...): ", err)); return err; } } return efd; }
JNIEXPORT jboolean JNICALL Java_io_netty_channel_epoll_Native_finishConnect(JNIEnv * env, jclass clazz, jint fd) { // connect may be done // return true if connection finished successfully // return false if connection is still in progress // throw exception if connection failed int optval; int res = getOption(env, fd, SOL_SOCKET, SO_ERROR, &optval, sizeof(optval)); if (res != 0) { // getOption failed throwIOException(env, exceptionMessage("finishConnect getOption failed: ", res)); return JNI_FALSE; } else if (optval == EINPROGRESS) { // connect still in progress return JNI_FALSE; } else if (optval == 0) { // connect succeeded return JNI_TRUE; } else { // connect failed throwIOException(env, exceptionMessage("Unable to connect to remote host: ", optval)); return JNI_FALSE; } }
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_accept(JNIEnv * env, jclass clazz, jint fd) { jint socketFd; int err; do { if (accept4) { socketFd = accept4(fd, NULL, 0, SOCK_NONBLOCK | SOCK_CLOEXEC); } else { socketFd = accept(fd, NULL, 0); } } while (socketFd == -1 && ((err = errno) == EINTR)); if (socketFd == -1) { if (err == EAGAIN || err == EWOULDBLOCK) { // Everything consumed so just return -1 here. return -1; } else { throwIOException(env, exceptionMessage("Error during accept(...): ", err)); return -1; } } if (accept4) { return socketFd; } else { // accept4 was not present so need two more sys-calls ... if (fcntl(socketFd, F_SETFD, FD_CLOEXEC) == -1) { throwIOException(env, exceptionMessage("Error during accept(...): ", err)); return -1; } if (fcntl(socketFd, F_SETFL, O_NONBLOCK) == -1) { throwIOException(env, exceptionMessage("Error during accept(...): ", err)); return -1; } } return socketFd; }
jint socket0(JNIEnv * env, jclass clazz, int type) { // TODO: Maybe also respect -Djava.net.preferIPv4Stack=true int fd = socket(socketType, type | SOCK_NONBLOCK, 0); if (fd == -1) { int err = errno; throwIOException(env, exceptionMessage("Error creating socket: ", err)); return -1; } else if (socketType == AF_INET6){ // Allow to listen /connect ipv4 and ipv6 int optval = 0; if (setOption(env, fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)) < 0) { // Something went wrong so close the fd and return here. setOption(...) itself throws the exception already. close(fd); return -1; } } return fd; }
JNIEXPORT jboolean JNICALL Java_io_netty_channel_epoll_Native_connect(JNIEnv * env, jclass clazz, jint fd, jbyteArray address, jint scopeId, jint port) { struct sockaddr_storage addr; init_sockaddr(env, address, scopeId, port, &addr); int res; int err; do { res = connect(fd, (struct sockaddr *) &addr, sizeof(addr)); } while (res == -1 && ((err = errno) == EINTR)); if (res < 0) { if (err == EINPROGRESS) { // connect not complete yet need to wait for EPOLLOUT event return JNI_FALSE; } throwIOException(env, exceptionMessage("Unable to connect to remote host: ", err)); return JNI_FALSE; } return JNI_TRUE; }
jint write0(JNIEnv * env, jclass clazz, jint fd, void *buffer, jint pos, jint limit) { ssize_t res; int err; do { res = write(fd, buffer + pos, (size_t) (limit - pos)); // keep on writing if it was interrupted } while(res == -1 && ((err = errno) == EINTR)); if (res < 0) { // network stack saturated... try again later if (err == EAGAIN || err == EWOULDBLOCK) { return 0; } if (err == EBADF) { throwClosedChannelException(env); return -1; } throwIOException(env, exceptionMessage("Error while write(...): ", err)); return -1; } return (jint) res; }
jlong writev0(JNIEnv * env, jclass clazz, jint fd, struct iovec iov[], jint length) { ssize_t res; int err; do { res = writev(fd, iov, length); // keep on writing if it was interrupted } while(res == -1 && ((err = errno) == EINTR)); if (res < 0) { if (err == EAGAIN || err == EWOULDBLOCK) { // network stack is saturated we will try again later return 0; } if (err == EBADF) { throwClosedChannelException(env); return -1; } throwIOException(env, exceptionMessage("Error while writev(...): ", err)); return -1; } return (jlong) res; }
JNIEXPORT jlong JNICALL Java_io_netty_channel_epoll_Native_sendfile(JNIEnv *env, jclass clazz, jint fd, jobject fileRegion, jlong off, jlong len) { jobject fileChannel = (*env)->GetObjectField(env, fileRegion, fileChannelFieldId); if (fileChannel == NULL) { throwRuntimeException(env, "Unable to obtain FileChannel from FileRegion"); return -1; } jobject fileDescriptor = (*env)->GetObjectField(env, fileChannel, fileDescriptorFieldId); if (fileDescriptor == NULL) { throwRuntimeException(env, "Unable to obtain FileDescriptor from FileChannel"); return -1; } jint srcFd = (*env)->GetIntField(env, fileDescriptor, fdFieldId); if (srcFd == -1) { throwRuntimeException(env, "Unable to obtain the fd from the FileDescriptor"); return -1; } ssize_t res; off_t offset = off; int err; do { res = sendfile(fd, srcFd, &offset, (size_t) len); } while (res == -1 && ((err = errno) == EINTR)); if (res < 0) { if (err == EAGAIN) { return 0; } throwIOException(env, exceptionMessage("Error during accept(...): ", err)); return -1; } if (res > 0) { // update the transfered field in DefaultFileRegion (*env)->SetLongField(env, fileRegion, transferedFieldId, off + res); } return res; }
void JsVm::fillTryCatch() { v8::Handle<v8::Value> exception = m_trycatch.Exception(); v8::String::Utf8Value exceptionMessage(exception); LOG(error) << *exceptionMessage; }
void throwIOExceptionErrorNo(JNIEnv* env, char* message, int errorNumber) { char* allocatedMessage = exceptionMessage(message, errorNumber); (*env)->ThrowNew(env, ioExceptionClass, allocatedMessage); free(allocatedMessage); }
JNIEXPORT void JNICALL Java_io_netty_channel_epoll_Native_epollCtlMod(JNIEnv * env, jclass clazz, jint efd, jint fd, jint flags, jint id) { if (epollCtl(env, efd, EPOLL_CTL_MOD, fd, flags, id) < 0) { int err = errno; throwRuntimeException(env, exceptionMessage("Error during calling epoll_ctl(...): ", err)); } }
JNIEXPORT void JNICALL Java_io_netty_channel_epoll_Native_listen(JNIEnv * env, jclass clazz, jint fd, jint backlog) { if(listen(fd, backlog) == -1) { int err = errno; throwIOException(env, exceptionMessage("Error during listen(...): ", err)); } }