Mercurial > hg > thermostat
view agent/ipc/windows-named-pipes/common/src/main/native/WinPipesNativeHelper.c @ 2589:a6ba41a449c8
[PATCH] Windows Named Pipes - preliminary implementation
A preliminary implementation of windows named pipes.
Does not set windoes named pipes as default IPC; remains TCP
reviewed-by: aazores, ebaron
review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-February/022126.html
author | Simon Tooke <stooke@redhat.com> |
---|---|
date | Fri, 10 Feb 2017 15:52:51 -0500 |
parents | |
children |
line wrap: on
line source
/* * Copyright 2012-2017 Red Hat, Inc. * * This file is part of Thermostat. * * Thermostat is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2, or (at your * option) any later version. * * Thermostat is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Thermostat; see the file COPYING. If not see * <http://www.gnu.org/licenses/>. * * Linking this code with other modules is making a combined work * based on this code. Thus, the terms and conditions of the GNU * General Public License cover the whole combination. * * As a special exception, the copyright holders of this code give * you permission to link this code with independent modules to * produce an executable, regardless of the license terms of these * independent modules, and to copy and distribute the resulting * executable under terms of your choice, provided that you also * meet, for each linked independent module, the terms and conditions * of the license of that module. An independent module is a module * which is not derived from or based on this code. If you modify * this code, you may extend this exception to your version of the * library, but you are not obligated to do so. If you do not wish * to do so, delete this exception statement from your version. */ #include "com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper.h" #include <jni.h> #include <unistd.h> #include <string.h> #include <assert.h> #if defined(_WIN32) # include <winsock2.h> # include <Windows.h> #endif #define PIPE_TIMEOUT 5000 //#define FILL_READ_BUFFER 1 static jint throw_IOException(JNIEnv *env, const char *message) { const char *class_name = "java/io/IOException"; jclass class = (*env)->FindClass(env, class_name); if (class == NULL) { return -1; } return (*env)->ThrowNew(env, class, message); } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: createNamedPipe0 * Signature: (Ljava/lang/String;II)J */ JNIEXPORT jlong JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_createNamedPipe0 (JNIEnv *env, jobject obj, jstring pipeName, jint instances, jint bufsize) { const char *pname = (*env)->GetStringUTFChars(env, pipeName, NULL); if (pname == NULL) { return 0; } HANDLE pipeHandle = CreateNamedPipe( pname, // pipe name PIPE_ACCESS_DUPLEX | // read/write access FILE_FLAG_OVERLAPPED, // overlapped mode PIPE_TYPE_MESSAGE | // message-type pipe PIPE_READMODE_MESSAGE | // message-read mode PIPE_WAIT, // blocking mode instances, // number of instances bufsize, // output buffer size bufsize, // input buffer size PIPE_TIMEOUT, // client time-out NULL); // default security attributes (*env)->ReleaseStringUTFChars(env, pipeName, pname); return (jlong)pipeHandle; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: openNamedPipe0 * Signature: (Ljava/lang/String;)J */ JNIEXPORT jlong JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_openExistingNamedPipe0 (JNIEnv *env, jobject obj, jstring pipeName) { const char *pname = (*env)->GetStringUTFChars(env, pipeName, NULL); if (pname == NULL) { return 0; } jlong hnd = (jlong)CreateFile( pname, // pipe name GENERIC_READ | // read and write access GENERIC_WRITE, 0, // no sharing NULL, // default security attributes OPEN_EXISTING, // opens existing pipe 0, // default attributes NULL); // no template file (*env)->ReleaseStringUTFChars(env, pipeName, pname); return (jlong)hnd; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: createEvent0 * Signature: ()J */ JNIEXPORT jlong JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_createEvent0 (JNIEnv *env, jobject obj, jboolean manual, jboolean initial) { return (jlong)CreateEvent(NULL, manual, initial, NULL); } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: resetEvent0 * Signature: (J)V */ JNIEXPORT void JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_resetEvent0 (JNIEnv *env, jobject obj, jlong eventHandle) { ResetEvent((HANDLE)eventHandle); } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: setEvent0 * Signature: (J)V */ JNIEXPORT void JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_setEvent0 (JNIEnv *env, jobject obj, jlong eventHandle) { SetEvent((HANDLE)eventHandle); } JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_getLastError0 (JNIEnv *env, jobject obj) { return GetLastError(); } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: connectNamedPipe0 * Signature: (JJ[D)Ljava/lang/String; * * return 0 if sucessfull, ERROR_IO_PENDING if still pending, or GetLastError() if failure */ JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_connectNamedPipe0 (JNIEnv *env, jobject obj, jlong pipeHandle, jobject ooverlapped) { OVERLAPPED* overlapped = (OVERLAPPED*)(*env)->GetDirectBufferAddress(env, ooverlapped); BOOL ret = ConnectNamedPipe((HANDLE)pipeHandle, overlapped); return ret ? GetLastError() : 0; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: disconnectnamedPipe0 * Signature: (J)Z */ JNIEXPORT jboolean JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_disconnectNamedPipe0 (JNIEnv *env, jobject obj, jlong pipeHandle) { return DisconnectNamedPipe((HANDLE)pipeHandle); } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: getNamedPipeClientProcessId0 * Signature: (J)J */ JNIEXPORT jlong JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_getNamedPipeClientProcessId0 (JNIEnv *env, jobject obj, jlong pipeHandle) { throw_IOException(env, "getNamedPipeClientProcessId0() not yet implemented"); return -1; // TODO - implement if needed } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: closeHandle0 * Signature: (J)Z */ JNIEXPORT jboolean JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_closeHandle0 (JNIEnv *env, jobject obj, jlong handle) { return CloseHandle((HANDLE)handle); } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: waitForMultipleObjects0 * Signature: (I[JZI)I */ JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_waitForMultipleObjects0 (JNIEnv *env, jobject obj, jint numObjects, jlongArray handles, jboolean waitForAll, jint millis) { void* eventHandles = (*env)->GetLongArrayElements(env, handles, NULL); int ret = WaitForMultipleObjects(numObjects, eventHandles, waitForAll, millis); (*env)->ReleaseLongArrayElements(env, handles, eventHandles, 0); return (jint) ret; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: getOverlappedResult0 * Signature: (JJ[DZ)J */ JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_getOverlappedResult0 (JNIEnv *env, jobject obj, jlong pipeHandle, jobject ooverlapped, jboolean wait) { OVERLAPPED* overlapped = (OVERLAPPED*)(*env)->GetDirectBufferAddress(env, ooverlapped); DWORD bytesTransferred = 0; BOOL success = GetOverlappedResult( (HANDLE)pipeHandle, overlapped, &bytesTransferred, wait ); return success ? bytesTransferred : (-bytesTransferred) - 1; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: readFileOverlapped0 * Signature: (JJ[D[BJ)J */ JNIEXPORT jboolean JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_readFileOverlapped0 (JNIEnv *env, jobject obj, jlong handle, jobject ooverlapped, jobject buffer, jint offset, jint bufsize) { OVERLAPPED* overlapped = (OVERLAPPED*)(*env)->GetDirectBufferAddress(env, ooverlapped); HANDLE hEvent = overlapped->hEvent; memset(overlapped, 0, sizeof(OVERLAPPED)); overlapped->hEvent = hEvent; jbyte* buf = (*env)->GetDirectBufferAddress(env, buffer); #if defined(FILL_READ_BUFFER) memset(buf + offset, 'r', (int)bufsize); #endif BOOL success = ReadFile( (HANDLE)handle, buf + offset, (int)bufsize, NULL, overlapped ); return success; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: readFile0 * Signature: (J[BJ)J */ JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_readFile0 (JNIEnv *env, jobject obj, jlong handle, jbyteArray array, jint offset, jint bufsize) { jbyte* buf = (*env)->GetByteArrayElements(env, array, 0); DWORD bytesTransferred = 0; BOOL success = ReadFile( (HANDLE)handle, buf + offset, (int)bufsize, &bytesTransferred, NULL ); (*env)->ReleaseByteArrayElements(env, array, buf, 0); return success ? bytesTransferred : (-bytesTransferred) - 1; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: writeFileOverlapped0 * Signature: (JJ[D[BJ)J */ JNIEXPORT jboolean JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_writeFileOverlapped0 (JNIEnv *env, jobject obj, jlong handle, jobject ooverlapped, jobject buffer, jint offset, jint bufsize) { OVERLAPPED* overlapped = (OVERLAPPED*)(*env)->GetDirectBufferAddress(env, ooverlapped); jbyte* buf = (*env)->GetDirectBufferAddress(env, buffer); HANDLE hEvent = overlapped->hEvent; memset(overlapped, 0, sizeof(OVERLAPPED)); overlapped->hEvent = hEvent; BOOL success = WriteFile( (HANDLE)handle, buf + offset, (int)bufsize, NULL, overlapped ); return success; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: writeFile0 * Signature: (J[BJ)J */ JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_writeFile0 (JNIEnv *env, jobject obj, jlong handle, jobject array, jint offset, jint bufsize) { jbyte* data = (*env)->GetByteArrayElements(env, array, 0); DWORD bytesTransferred = 0; BOOL success = WriteFile( (HANDLE)handle, data + offset, (int)bufsize, &bytesTransferred, 0 ); (*env)->ReleaseByteArrayElements(env, array, data, JNI_ABORT); return success ? bytesTransferred : (-bytesTransferred) - 1; } JNIEXPORT jlong JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_getConstantWaitObject0 (JNIEnv *env, jobject obj) { return (jlong)WAIT_OBJECT_0; } JNIEXPORT jlong JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_getConstantInfinite0 (JNIEnv *env, jobject obj) { return (jlong)INFINITE; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: getConstantErrorIOPending0 * Signature: ()J */ JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_getConstantErrorIOPending0 (JNIEnv *env, jobject obj) { return ERROR_IO_PENDING; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: getConstantErrorIOIncomplete0 * Signature: ()J */ JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_getConstantErrorIOIncomplete0 (JNIEnv *env, jobject obj) { return ERROR_IO_INCOMPLETE; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: getConstantErrorHandleEOF0 * Signature: ()J */ JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_getConstantErrorHandleEOF0 (JNIEnv *env, jobject obj) { return ERROR_HANDLE_EOF; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: getConstantErrorMoreData0 * Signature: ()J */ JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_getConstantErrorMoreData0 (JNIEnv *env, jobject obj) { return ERROR_MORE_DATA; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: getConstantErrorPipeBusy0 * Signature: ()J */ JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_getConstantErrorPipeBusy0 (JNIEnv *env, jobject obj) { return ERROR_PIPE_BUSY; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: getConstantErrorPipeConnected0 * Signature: ()J */ JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_getConstantErrorPipeConnected0 (JNIEnv *env, jobject obj) { return ERROR_PIPE_CONNECTED; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: getConstantInvalidHandle0 * Signature: ()J */ JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_getConstantInvalidHandle0 (JNIEnv *env, jobject obj) { return (jint)INVALID_HANDLE_VALUE; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: getConstantErrorBrokenPipe0 * Signature: ()J */ JNIEXPORT jint JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_getConstantErrorBrokenPipe0 (JNIEnv *env, jobject obj) { return (jint)ERROR_BROKEN_PIPE; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: createDirectBuffer0 * Signature: (I)Ljava/nio/ByteBuffer; */ JNIEXPORT jobject JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_createDirectBuffer0 (JNIEnv *env, jobject obj, jint bufsize) { void* buffer = malloc(bufsize); jobject bytebuffer = (*env)->NewDirectByteBuffer(env, buffer, bufsize); return bytebuffer; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: createDirectOverlapStruct0 * Signature: ()Ljava/nio/ByteBuffer; */ JNIEXPORT jobject JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_createDirectOverlapStruct0 (JNIEnv *env, jobject obj, jlong eHandle) { const int bufsize = sizeof(OVERLAPPED); OVERLAPPED* overlapped = (OVERLAPPED*)calloc(bufsize, 1); overlapped->hEvent = (HANDLE)eHandle; jobject bytebuffer = (*env)->NewDirectByteBuffer(env, overlapped, bufsize); return bytebuffer; } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: freeDirectBuffer0 * Signature: (Ljava/nio/ByteBuffer;)V */ JNIEXPORT void JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_freeDirectBuffer0 (JNIEnv *env, jobject obj, jobject bytebuffer) { void *buffer = (*env)->GetDirectBufferAddress(env, bytebuffer); free(buffer); } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: cancelIo0 * Signature: (J)Z */ JNIEXPORT jboolean JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_cancelIo0 (JNIEnv *env, jobject obj, jlong pipeHandle) { return (jboolean)CancelIo(pipeHandle); } /* * Class: com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper * Method: cancelIoEx0 * Signature: (JLjava/nio/ByteBuffer;)Z */ JNIEXPORT jboolean JNICALL Java_com_redhat_thermostat_agent_ipc_winpipes_common_internal_WinPipesNativeHelper_cancelIoEx0 (JNIEnv *env, jobject obj, jlong pipeHandle, jobject ooverlapped) { OVERLAPPED* overlapped = ooverlapped == 0 ? 0 : (OVERLAPPED*)(*env)->GetDirectBufferAddress(env, ooverlapped); return (jboolean)CancelIoEx(pipeHandle, ooverlapped); }