Esempio n. 1
0
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    read
	 * Signature: (Ljava/io/FileDescriptor;[BII)I
	 */
	JNIEXPORT jint JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_read
	(JNIEnv * env, jclass clazz, jobject fd, jbyteArray jbuf, jint offset, jint length) {
		jbyte *buf = (*env)->GetByteArrayElements(env, jbuf, NULL);
		if(buf == NULL) {
			return -1; // OOME
		}

		int handle = org_newsclub_net_unix_NativeUnixSocket_getFD(env, fd);
		
		ssize_t count = read(handle, &(buf[offset]), length);
		(*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);
		
        if(count == 0) {
            // read(2) returns 0 on EOF. Java returns -1.
            return -1;
        } else if(count == -1) {
            // read(2) returns -1 on error. Java throws an Exception.
            
//          Removed since non-blocking is not yet supported
//			if(errno == EAGAIN || errno == EWOULDBLOCK) {
//				return 0;
//			}
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), NULL);
			return -1;
		}
		
		return count;
	}
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    setSocketOptionInt
	 * Signature: (Ljava/io/FileDescriptor;II)V
	 */
	JNIEXPORT void JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_setSocketOptionInt
	(JNIEnv * env, jclass clazz, jobject fd, jint optID, jint value) {
		int handle = org_newsclub_net_unix_NativeUnixSocket_getFD(env, fd);
		
		if(optID == SO_SNDTIMEO || optID == SO_RCVTIMEO) {
			struct timeval optVal;
			optVal.tv_sec = value / 1000;
			optVal.tv_usec = (value % 1000) * 1000;
			int ret = setsockopt(handle, SOL_SOCKET, optID, &optVal, sizeof(optVal));
			if(ret == -1) {
				org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), NULL);
			}
			return;
		} else if(optID == SO_LINGER) {
			struct linger optVal;
			
			optVal.l_onoff = value >= 0;
			optVal.l_linger = value >= 0 ? value : 0;

			int ret = setsockopt(handle, SOL_SOCKET, optID, &optVal, sizeof(optVal));
			if(ret == -1) {
				org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), NULL);
			}
			return;
		}
		
		
		int optVal = (int)value;
		
		int ret = setsockopt(handle, SOL_SOCKET, optID, &optVal, sizeof(optVal));
		if(ret == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), NULL);
		}
	}
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    close
	 * Signature: (Ljava/io/FileDescriptor;)V
	 */
	JNIEXPORT void JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_close
	(JNIEnv * env, jclass clazz, jobject fd) {
		int handle = org_newsclub_net_unix_NativeUnixSocket_getFD(env, fd);
		int ret = close(handle);
		if(ret == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), NULL);
		}
	}
Esempio n. 4
0
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    receiveCredentials
	 * Signature: (Ljava/io/FileDescriptor;)B
	 */
	JNIEXPORT jintArray JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_receiveCredentials
	  (JNIEnv *env, jclass clazz, jobject fd) {
		  int handle = org_newsclub_net_unix_NativeUnixSocket_getFD(env, fd);
		  struct msghdr msg;
		  char iov_buf = 0;
		  struct iovec iov;
		  msg.msg_name = NULL;
		  msg.msg_namelen = 0;
		  msg.msg_flags = 0;
		  msg.msg_iov = &iov;
		  msg.msg_iovlen = 1;
		  msg.msg_control = NULL;
		  msg.msg_controllen = 0;
		  iov.iov_base = &iov_buf;
		  iov.iov_len = 1;
		  jintArray result;

#ifdef SCM_CREDENTIALS
		  char buf[CMSG_SPACE(sizeof(struct ucred))];
		  msg.msg_control = buf;
		  msg.msg_controllen = sizeof buf;
		  struct cmsghdr *cmsg;
		  struct ucred *creds = NULL;
#endif

		  recvmsg(handle, &msg, 0);

#ifdef SCM_CREDENTIALS
		  for (cmsg = CMSG_FIRSTHDR(&msg);
				  cmsg != NULL;
				  cmsg = CMSG_NXTHDR(&msg,cmsg)) {
			  if (cmsg->cmsg_level == SOL_SOCKET
					  && cmsg->cmsg_type == SCM_CREDENTIALS) {
				  creds = (struct ucred *) CMSG_DATA(cmsg);        
				  break;
			  }
		  }
		  if (NULL != creds) {
		  	  result=(*env)->NewIntArray(env, 4); 
			  jint cred_array[3];
			  cred_array[0] = creds->pid;
			  cred_array[1] = creds->uid;
			  cred_array[2] = creds->gid;

			  jint data = iov_buf;
			  (*env)->SetIntArrayRegion(env, result, 0, 1, &data);
			  (*env)->SetIntArrayRegion(env, result, 1, 3, &cred_array[0]);
			  return result;
		  } 
#endif

		  result=(*env)->NewIntArray(env, 1);
		  jint data = iov_buf;
                  (*env)->SetIntArrayRegion(env, result, 0, 1, &data);

		  return result;
	}
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    available
	 * Signature: (Ljava/io/FileDescriptor;)I
	 */
	JNIEXPORT jint JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_available
	(JNIEnv * env, jclass clazz, jobject fd) {
		jbyte buf = '\0';
		
		int handle = org_newsclub_net_unix_NativeUnixSocket_getFD(env, fd);
		
		ssize_t count = recv(handle, &buf, 1, MSG_PEEK);
		
		return count;
	}
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    listen
	 * Signature: (Ljava/io/FileDescriptor;I)V
	 */
	JNIEXPORT void JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_listen
	(JNIEnv * env, jclass clazz, jobject fd, jint backlog) {
		int serverHandle = org_newsclub_net_unix_NativeUnixSocket_getFD(env, fd);

		int listenRes = listen(serverHandle, backlog);
		if(listenRes == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), NULL);
			return;
		}
	}
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    shutdown
	 * Signature: (Ljava/io/FileDescriptor;I)V
	 */
	JNIEXPORT void JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_shutdown
	(JNIEnv * env, jclass clazz, jobject fd, jint mode) {
		int handle = org_newsclub_net_unix_NativeUnixSocket_getFD(env, fd);
		int ret = shutdown(handle, mode);
		if(ret == -1) {
			if(errno == ENOTCONN) {
				// ignore
				return;
			}
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), NULL);
		}
	}
Esempio n. 8
0
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    accept
	 * Signature: (Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;)V
	 */
	JNIEXPORT void JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_accept
	(JNIEnv * env, jclass clazz, jstring file, jobject fdServer, jobject fd, jboolean abstract) {
		
		const char* socketFile = (*env)->GetStringUTFChars(env, file, NULL);
		if(socketFile == NULL) {
			return; // OOME
		}
		if(strlen(socketFile) >= 104) {
			(*env)->ReleaseStringUTFChars(env, file, socketFile);
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, "Pathname too long for socket", file);
			return;
		}
		
		int serverHandle = org_newsclub_net_unix_NativeUnixSocket_getFD(env, fdServer);
	

		struct sockaddr_un su;
		memset(&su, 0, sizeof(struct sockaddr_un));
		su.sun_family = AF_UNIX;
		#ifdef junixsocket_have_sun_len
		  su.sun_len = (sizeof(su) - sizeof(su.sun_path) + strlen(su.sun_path));
		#endif
		
		size_t pathlen = 0;
		if ( abstract == JNI_TRUE ) {
			strcpy(su.sun_path+1, socketFile);
			pathlen = strlen(socketFile) + 1;
		} else {
			strcpy(su.sun_path, socketFile);
			pathlen = strlen(socketFile);
		}

		(*env)->ReleaseStringUTFChars(env, file, socketFile);
		
		socklen_t suLength = pathlen + sizeof(su.sun_family)
		#ifdef junixsocket_have_sun_len
		 + sizeof(su.sun_len)
	        #endif
        	;
		
		int socketHandle = accept(serverHandle, (struct sockaddr *)&su, &suLength);
		if(socketHandle == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), file);
			return;
		}
		
		org_newsclub_net_unix_NativeUnixSocket_initFD(env, fd, socketHandle);
		return;
	}
Esempio n. 9
0
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    available
	 * Signature: (Ljava/io/FileDescriptor;)I
	 */
	JNIEXPORT jint JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_available
	(JNIEnv * env, jclass clazz, jobject fd) {
		int handle = org_newsclub_net_unix_NativeUnixSocket_getFD(env, fd);
		
        // the following would actually block and keep the peek'ed byte in the buffer
		//ssize_t count = recv(handle, &buf, 1, MSG_PEEK);
        
        int count;
        ioctl(handle, FIONREAD, &count);
		if(count == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), NULL);
			return -1;
		}
		
		return count;
	}
Esempio n. 10
0
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    getSocketOptionInt
	 * Signature: (Ljava/io/FileDescriptor;I)I
	 */
	JNIEXPORT jint JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_getSocketOptionInt
	(JNIEnv * env, jclass clazz, jobject fd, jint optID) {
		int handle = org_newsclub_net_unix_NativeUnixSocket_getFD(env, fd);
        
        optID = convertSocketOptionToNative(optID);
        if(optID == -1) {
            org_newsclub_net_unix_NativeUnixSocket_throwException(env, "Unsupported socket option", NULL);
            return -1;
        }
		
        if(optID == SO_SNDTIMEO || optID == SO_RCVTIMEO) {
			struct timeval optVal;
			socklen_t optLen = sizeof(optVal);
			int ret = getsockopt(handle, SOL_SOCKET, optID, &optVal, &optLen);
			if(ret == -1) {
				org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), NULL);
				return -1;
			}
			return optVal.tv_sec * 1000 + optVal.tv_usec / 1000;
		} else if(optID == SO_LINGER) {
			struct linger optVal;
			socklen_t optLen = sizeof(optVal);
			
			int ret = getsockopt(handle, SOL_SOCKET, optID, &optVal, &optLen);
			if(ret == -1) {
				org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), NULL);
				return -1;
			}
			if(optVal.l_onoff == 0) {
				return -1;
			} else {
				return optVal.l_linger;
			}
		}
		
		int optVal;
		socklen_t optLen = sizeof(optVal);
		
		int ret = getsockopt(handle, SOL_SOCKET, optID, &optVal, &optLen);
		if(ret == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), NULL);
			return -1;
		}
		
		return optVal;
	}
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    write
	 * Signature: (Ljava/io/FileDescriptor;[BII)I
	 */
	JNIEXPORT jint JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_write
	(JNIEnv * env, jclass clazz, jobject fd, jbyteArray jbuf, jint offset, jint length) {
		jbyte *buf = (*env)->GetByteArrayElements(env, jbuf, NULL);
		if(buf == NULL) {
			return -1; // OOME
		}
		int handle = org_newsclub_net_unix_NativeUnixSocket_getFD(env, fd);

		ssize_t count = write(handle, &buf[offset], length);
		(*env)->ReleaseByteArrayElements(env, jbuf, buf, 0);

		if(count == -1) {
			if(errno == EAGAIN || errno == EWOULDBLOCK) {
				return 0;
			}
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), NULL);
			return -1;
		}
		
		return count;	
	}
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    accept
	 * Signature: (Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;)V
	 */
	JNIEXPORT void JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_accept
	(JNIEnv * env, jclass clazz, jstring file, jobject fdServer, jobject fd) {
		
		const char* socketFile = (*env)->GetStringUTFChars(env, file, NULL);
		if(socketFile == NULL) {
			return; // OOME
		}
		if(strlen(socketFile) >= 104) {
			(*env)->ReleaseStringUTFChars(env, file, socketFile);
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, "Pathname too long for socket", file);
			return;
		}
		
		int serverHandle = org_newsclub_net_unix_NativeUnixSocket_getFD(env, fdServer);
		
		struct sockaddr_un su;
		su.sun_family = AF_UNIX;
#ifndef __linux__
		su.sun_len = (sizeof(su) - sizeof(su.sun_path) + strlen(su.sun_path));
#endif
		strcpy(su.sun_path, socketFile);
		(*env)->ReleaseStringUTFChars(env, file, socketFile);
		
		socklen_t suLength = strlen(su.sun_path) + sizeof(su.sun_family)
#ifndef __linux__
		+ sizeof(su.sun_len)
#endif
		;
		
		int socketHandle = accept(serverHandle, (struct sockaddr *)&su, &suLength);
		if(socketHandle == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), file);
			return;
		}
		
		org_newsclub_net_unix_NativeUnixSocket_initFD(env, fd, socketHandle);
		return;
	}
Esempio n. 13
0
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    sendCredentials
	 * Signature: (Ljava/io/FileDescriptor;B)V
	 */
	JNIEXPORT void JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_sendCredentials
	  (JNIEnv *env, jclass clazz, jobject fd, jbyte data) {
		  int handle = org_newsclub_net_unix_NativeUnixSocket_getFD(env, fd);
		  struct msghdr msg;
		  struct iovec iov;
		  msg.msg_name = NULL;
		  msg.msg_namelen = 0;
		  msg.msg_flags = 0;
		  msg.msg_iov = &iov;
		  msg.msg_iovlen = 1;
		  msg.msg_control = NULL;
		  msg.msg_controllen = 0;
		  iov.iov_base = &data;
		  iov.iov_len = 1;

#ifdef SCM_CREDENTIALS
		  char buf[CMSG_SPACE(sizeof(struct ucred))];
		  msg.msg_control = buf;
		  msg.msg_controllen = sizeof buf;
		  struct cmsghdr *cmsg;
		  struct ucred *creds;

		  cmsg = CMSG_FIRSTHDR(&msg);
		  cmsg->cmsg_level = SOL_SOCKET;
		  cmsg->cmsg_type = SCM_CREDENTIALS;
		  cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
		  /* Initialize the payload: */
		  creds = (struct ucred *)CMSG_DATA(cmsg);
		  creds->pid = getpid();
		  creds->uid = getuid();
		  creds->gid = getgid();
#endif

		  int rv = sendmsg(handle, &msg, 0);
		  if (-1 == rv) {
		  	org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(rv), NULL);
		  }
	}