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;
}
示例#10
0
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;
	}
}