JNIEXPORT void JNICALL Java_de_entropia_can_CanSocket__1close (JNIEnv *env, jobject obj, jint fd) { if (close(fd) == -1) { throwIOExceptionErrno(env, errno); } }
JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1discoverInterfaceIndex (JNIEnv *env, jclass clazz, jint socketFd, jstring ifName) { struct ifreq ifreq; const jsize ifNameSize = env->GetStringUTFLength(ifName); if (ifNameSize > IFNAMSIZ-1) { throwIllegalArgumentException(env, "illegal interface name"); return -1; } /* fetch interface name */ memset(&ifreq, 0x0, sizeof(ifreq)); env->GetStringUTFRegion(ifName, 0, ifNameSize, ifreq.ifr_name); if (env->ExceptionCheck() == JNI_TRUE) { return -1; } /* discover interface id */ const int err = ioctl(socketFd, SIOCGIFINDEX, &ifreq); if (err == -1) { throwIOExceptionErrno(env, errno); return -1; } else { return ifreq.ifr_ifindex; } }
JNIEXPORT void JNICALL Java_de_entropia_can_CanSocket__1sendFrame (JNIEnv *env, jclass obj, jint fd, jint if_idx, jint canid, jbyteArray data) { const int flags = 0; ssize_t nbytes; struct sockaddr_can addr; struct can_frame frame; memset(&addr, 0, sizeof(addr)); memset(&frame, 0, sizeof(frame)); addr.can_family = AF_CAN; addr.can_ifindex = if_idx; const jsize len = env->GetArrayLength(data); if (env->ExceptionCheck() == JNI_TRUE) { return; } frame.can_id = canid; frame.can_dlc = static_cast<__u8>(len); env->GetByteArrayRegion(data, 0, len, reinterpret_cast<jbyte *>(&frame.data)); if (env->ExceptionCheck() == JNI_TRUE) { return; } nbytes = sendto(fd, &frame, sizeof(frame), flags, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)); if (nbytes == -1) { throwIOExceptionErrno(env, errno); } else if (nbytes != sizeof(frame)) { throwIOExceptionMsg(env, "send partial frame"); } }
JNIEXPORT void JNICALL Java_de_entropia_can_CanSocket__1setsockopt (JNIEnv *env, jclass obj, jint fd, jint op, jint stat) { const int _stat = stat; if (setsockopt(fd, SOL_CAN_RAW, op, &_stat, sizeof(_stat)) == -1) { throwIOExceptionErrno(env, errno); } }
static jint newCanSocket(JNIEnv *env, int socket_type, int protocol) { const int fd = socket(PF_CAN, socket_type, protocol); if (fd != -1) { return fd; } throwIOExceptionErrno(env, errno); return -1; }
JNIEXPORT void JNICALL Java_de_entropia_can_CanSocket__1bindToSocket (JNIEnv *env, jclass obj, jint fd, jint ifIndex) { struct sockaddr_can addr; addr.can_family = AF_CAN; addr.can_ifindex = ifIndex; if (bind(fd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)) != 0) { throwIOExceptionErrno(env, errno); } }
JNIEXPORT jobject JNICALL Java_de_entropia_can_CanSocket__1recvFrame (JNIEnv *env, jclass obj, jint fd) { const int flags = 0; ssize_t nbytes; struct sockaddr_can addr; socklen_t len = sizeof(addr); struct can_frame frame; memset(&addr, 0, sizeof(addr)); memset(&frame, 0, sizeof(frame)); nbytes = recvfrom(fd, &frame, sizeof(frame), flags, reinterpret_cast<struct sockaddr *>(&addr), &len); if (len != sizeof(addr)) { throwIllegalArgumentException(env, "illegal AF_CAN address"); return nullptr; } if (nbytes == -1) { throwIOExceptionErrno(env, errno); return nullptr; } else if (nbytes != sizeof(frame)) { throwIOExceptionMsg(env, "invalid length of received frame"); return nullptr; } const jsize fsize = static_cast<jsize>(std::min(static_cast<size_t>(frame.can_dlc), nbytes - offsetof(struct can_frame, data))); const jclass can_frame_clazz = env->FindClass("de/entropia/can/" "CanSocket$CanFrame"); if (can_frame_clazz == nullptr) { return nullptr; } const jmethodID can_frame_cstr = env->GetMethodID(can_frame_clazz, "<init>", "(II[B)V"); if (can_frame_cstr == nullptr) { return nullptr; } const jbyteArray data = env->NewByteArray(fsize); if (data == nullptr) { if (env->ExceptionCheck() != JNI_TRUE) { throwOutOfMemoryError(env, "could not allocate ByteArray"); } return nullptr; } env->SetByteArrayRegion(data, 0, fsize, reinterpret_cast<jbyte *>(&frame.data)); if (env->ExceptionCheck() == JNI_TRUE) { return nullptr; } const jobject ret = env->NewObject(can_frame_clazz, can_frame_cstr, addr.can_ifindex, frame.can_id, data); return ret; }
JNIEXPORT jstring JNICALL Java_de_entropia_can_CanSocket__1discoverInterfaceName (JNIEnv *env, jclass obj, jint fd, jint ifIdx) { struct ifreq ifreq; memset(&ifreq, 0x0, sizeof(ifreq)); ifreq.ifr_ifindex = ifIdx; if (ioctl(fd, SIOCGIFNAME, &ifreq) == -1) { throwIOExceptionErrno(env, errno); return nullptr; } const jstring ifname = env->NewStringUTF(ifreq.ifr_name); return ifname; }
JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1getsockopt (JNIEnv *env, jclass obj, jint fd, jint op) { int _stat = 0; socklen_t len = sizeof(_stat); if (getsockopt(fd, SOL_CAN_RAW, op, &_stat, &len) == -1) { throwIOExceptionErrno(env, errno); } if (len != sizeof(_stat)) { throwIllegalArgumentException(env, "setsockopt return size is different"); return -1; } return _stat; }
JNIEXPORT void JNICALL Java_de_entropia_can_CanSocket__1setfilter (JNIEnv *env, jclass obj, jint fd, jintArray fid, jint fmask) { jsize len = env->GetArrayLength(fid); struct can_filter rfilter[len]; jint *body = env->GetIntArrayElements(fid, 0); int i; for (i=0; i<len; i++) { rfilter[i].can_id = body[i]; rfilter[i].can_mask = fmask; } env->ReleaseIntArrayElements(fid, body, 0); if (setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter))){ throwIOExceptionErrno(env, errno); } }
JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1fetchInterfaceMtu (JNIEnv *env, jclass obj, jint fd, jstring ifName) { struct ifreq ifreq; const jsize ifNameSize = env->GetStringUTFLength(ifName); if (ifNameSize > IFNAMSIZ-1) { throwIllegalArgumentException(env, "illegal interface name"); return -1; } memset(&ifreq, 0x0, sizeof(ifreq)); env->GetStringUTFRegion(ifName, 0, ifNameSize, ifreq.ifr_name); if (env->ExceptionCheck() == JNI_TRUE) { return -1; } if (ioctl(fd, SIOCGIFMTU, &ifreq) == -1) { throwIOExceptionErrno(env, errno); return -1; } else { return ifreq.ifr_mtu; } }