Esempio n. 1
0
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    connect
	 * Signature: (Ljava/lang/String;Ljava/io/FileDescriptor;)V
	 */
	JNIEXPORT void JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_connect
	(JNIEnv * env, jclass clazz, jstring file, jobject fd, jboolean abstract, jboolean dgram) {
		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 sockType = SOCK_STREAM;

		if ( dgram == JNI_TRUE ) {
			sockType = SOCK_DGRAM;
		}

		int socketHandle = socket(AF_UNIX, sockType, 0);
		if(socketHandle == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), file);
			return;
		}


		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 ret = connect(socketHandle, (struct sockaddr *)&su, suLength);
		if(ret == -1) {
            close(socketHandle);
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), file);
			return;
		}
	
		org_newsclub_net_unix_NativeUnixSocket_initFD(env, fd, socketHandle);
	}
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    bind
	 * Signature: (Ljava/lang/String;Ljava/io/FileDescriptor;I)V
	 */
	JNIEXPORT void JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_bind
	(JNIEnv * env, jclass clazz, jstring file, jobject fd, jint backlog) {
		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 = socket(AF_UNIX, SOCK_STREAM, 0);
		if(serverHandle == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env,strerror(errno), file);
			return;
		}
		
		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 bindRes = bind(serverHandle, (struct sockaddr *)&su, suLength);
		
		if(bindRes == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), file);
			return;
		}
		
		int chmodRes = chmod(su.sun_path, 0666);
		if(chmodRes == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), file);
		}
		
		int listenRes = listen(serverHandle, backlog);
		if(listenRes == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), file);
			return;
		}
		
		org_newsclub_net_unix_NativeUnixSocket_initFD(env, fd, serverHandle);
	}		
	/*
	 * 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. 4
0
	/*
	 * Class:     org_newsclub_net_unix_NativeUnixSocket
	 * Method:    bind
	 * Signature: (Ljava/lang/String;Ljava/io/FileDescriptor;I)V
	 */
	JNIEXPORT void JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_bind
	(JNIEnv * env, jclass clazz, jstring file, jobject fd, jint backlog, jboolean abstract, jboolean dgram) {
		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 sockType = SOCK_STREAM;

		if ( dgram == JNI_TRUE ) {
			sockType = SOCK_DGRAM;
		}
		
		int serverHandle = socket(AF_UNIX, sockType, 0);
		if(serverHandle == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env,strerror(errno), file);
			return;
		}
        

        	// This block is only prophylactic, as SO_REUSEADDR seems not to work with AF_UNIX
	        int optVal = 1;
		int ret = setsockopt(serverHandle, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(optVal));
		if(ret == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), NULL);
		}        
		
		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 bindRes = bind(serverHandle, (struct sockaddr *)&su, suLength);
		
		if(bindRes == -1) {
			int myErr = errno;
			if(errno == EADDRINUSE) {
				// Let's check whether the address *really* is in use.
				// Maybe it's just a dead reference

				// if the given file exists, but is not a socket, ENOTSOCK is returned
				// if access is denied, EACCESS is returned
				ret = connect(serverHandle, (struct sockaddr *)&su, suLength);

				if(ret == -1 && errno == ECONNREFUSED) {
					// assume non-connected socket

					close(serverHandle);
					if(unlink(socketFile) == -1) {
						org_newsclub_net_unix_NativeUnixSocket_throwException(env,strerror(errno), file);
						return;
					}

					serverHandle = socket(AF_UNIX, SOCK_STREAM, 0);
					if(serverHandle == -1) {
						org_newsclub_net_unix_NativeUnixSocket_throwException(env,strerror(errno), file);
						return;
					}

					bindRes = bind(serverHandle, (struct sockaddr *)&su, suLength);
					if(bindRes == -1) {
						close(serverHandle);
						org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(myErr), file);
						return;
					}
				} else {
					close(serverHandle);
					org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(myErr), file);
					return;
				}
			} else {
				close(serverHandle);
				org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(myErr), file);
				return;
			}
		}

		if ( abstract == JNI_FALSE ) {
			int chmodRes = chmod(su.sun_path, 0666);
			if(chmodRes == -1) {
				org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), file);
			}
		}
		
		int listenRes = listen(serverHandle, backlog);
		if(listenRes == -1) {
			org_newsclub_net_unix_NativeUnixSocket_throwException(env, strerror(errno), file);
			return;
		}
		
		org_newsclub_net_unix_NativeUnixSocket_initFD(env, fd, serverHandle);
	}