Mercurial > hg > thermostat
view agent/ipc/windows-named-pipes/common/src/main/java/com/redhat/thermostat/agent/ipc/winpipes/common/internal/WinPipesNativeHelper.java @ 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. */ package com.redhat.thermostat.agent.ipc.winpipes.common.internal; import com.redhat.thermostat.shared.config.NativeLibraryResolver; import java.io.IOException; import java.nio.ByteBuffer; /** * Wrapper for Windows native methods pertaining to named pipes */ public class WinPipesNativeHelper { public static WinPipesNativeHelper INSTANCE = new WinPipesNativeHelper(); static { String lib = NativeLibraryResolver.getAbsoluteLibraryPath("WinPipesNativeWrapper"); System.load(lib); } // windows constants public static final long WAIT_OBJECT_0 = getConstantWaitObject0(); public static final long INVALID_HANDLE = 0; public static final long INFINITE = getConstantInfinite0(); // windows 'error' codes public static final int ERROR_SUCCESS = 0; public static final int ERROR_IO_PENDING = getConstantErrorIOPending0(); public static final int ERROR_IO_INCOMPLETE = getConstantErrorIOIncomplete0(); public static final int ERROR_HANDLE_EOF = getConstantErrorHandleEOF0(); public static final int ERROR_MORE_DATA = getConstantErrorMoreData0(); public static final int ERROR_PIPE_BUSY = getConstantErrorPipeBusy0(); public static final int ERROR_BROKEN_PIPE = getConstantErrorBrokenPipe0(); public static final int INVALID_HANDLE_VALUE = getConstantInvalidHandle0(); public static final int ERROR_PIPE_CONNECTED = getConstantErrorPipeConnected0(); private WinPipesNativeHelper() { } public ByteBuffer createDirectBuffer(int buffersize) { final ByteBuffer buf = createDirectBuffer0(buffersize); buf.limit(0); return buf; } public ByteBuffer createDirectOverlapStruct(long eHandle) { return createDirectOverlapStruct0(eHandle); } public void freeDirectBuffer(final ByteBuffer byteBuffer) throws IOException { ensureDirectBuffer(byteBuffer); freeDirectBuffer0(byteBuffer); } public long createNamedPipe(final String pipeName, int instances, int buffersize) { return createNamedPipe0(pipeName, instances, buffersize); } /** * Open existing named pipe (as client, for synchronous access) * @param pipeName name of Windows named pipe e.g. '\\.\pipe\thermostat-pipe-command-channel' * @return windows handle or 0 if failure */ long openNamedPipe(final String pipeName) { return openExistingNamedPipe0(pipeName); } public long createEvent() { return createEvent0(true, false); } public void resetEvent(long eventHandle) { resetEvent0(eventHandle); } public void setEvent(long eventHandle) { setEvent0(eventHandle); } public int getLastError() { return getLastError0(); } /** * Wait for a client connection on this pipe * * The eventHandle will be inserted into the OVERLAP struct by the native code * (Java can't do this as the OOVERLAP struct is opaque to Java) * * @param pipeHandle pipe handle * @param ooverlapped contiguous array used to store a Windows OVERLAPPED structure * @return 0 if sucessful, ERROR_IO_PENDING if pending, or other error code on failure */ public int connectNamedPipe(long pipeHandle, ByteBuffer ooverlapped) throws IOException { ensureDirectBuffer(ooverlapped); return connectNamedPipe0(pipeHandle, ooverlapped); } public boolean disconnectNamedPipe(long pipeHandle) { return disconnectNamedPipe0(pipeHandle); } public long getNamedPipeClientProcessId(long pipeHandle) { return getNamedPipeClientProcessId0(pipeHandle); } public boolean closeHandle(long handle) { return closeHandle0(handle); } public int waitForMultipleObjects(int n, long[] ehandles, boolean waitAll, int millis) { return waitForMultipleObjects0(n, ehandles, waitAll, millis); } /** * get result of overlapped operation * * @param pipeHandle handle * @param ooverlapped buffer to store Windows OVERLAPPED structure * @param wait true to wait for result, false to return immediately * @return bytes transferred (>= 0) if success, (- bytes transferred -1) if failure */ public int getOverlappedResult(long pipeHandle, ByteBuffer ooverlapped, boolean wait) throws IOException { ensureDirectBuffer(ooverlapped); return getOverlappedResult0(pipeHandle, ooverlapped, wait); } /** * Read from a file in overlapped mode * * The eventHandle will be inserted into the OVERLAP struct by the native code * (Java can't do this as the OOVERLAP struct is opaque to Java) * * @param pipeHandle pipe handle * @param ooverlapped contiguous array used to store a Windows OVERLAPPED structure * @param buffer byte buffer to be read into * @return true if successful */ public boolean readFileOverlapped(long pipeHandle, ByteBuffer ooverlapped, ByteBuffer buffer) throws IOException { ensureDirectBuffer(ooverlapped); ensureDirectBuffer(buffer); return readFileOverlapped0(pipeHandle, ooverlapped, buffer, buffer.position(), buffer.remaining()); } /** * Read from a file in syncronous mode * * @param pipeHandle pipe handle * @param buffer byte buffer to be read into * @return >= 0 if 0 or more bytes read, -1 if error */ int readFile(long pipeHandle, ByteBuffer buffer) { int count = readFile0(pipeHandle, buffer.array(), buffer.position(), buffer.remaining()); if (count >= 0) { buffer.position(buffer.position() + count); } return count; } /** * Write to a file in overlapped mode * * The eventHandle will be inserted into the OVERLAP struct by the native code * (Java can't do this as the OOVERLAP struct is opaque to Java) * * @param pipeHandle pipe handle * @param ooverlapped contiguous array used to store a Windows OVERLAPPED structure * @param buffer byte buffer to be written * @return true if IO pending, false if error */ public boolean writeFileOverlapped(long pipeHandle, ByteBuffer ooverlapped, ByteBuffer buffer) throws IOException { ensureDirectBuffer(ooverlapped); ensureDirectBuffer(buffer); return writeFileOverlapped0(pipeHandle, ooverlapped, buffer, buffer.position(), buffer.remaining()); // don't modify buffer's position() here, becuase need to wait until the buffer has been fully written } /** * Write to a file in synchronous mode * * @param pipeHandle pipe handle * @param buffer byte buffer to be written * @return >= 0 if 0 or more bytes written, -1 if error */ public int writeFile(long pipeHandle, ByteBuffer buffer) { final int count = writeFile0(pipeHandle, buffer.array(), buffer.position(), buffer.remaining()); if (count > 0) buffer.position(buffer.position() + count); return count; } /** * Write to a file in synchronous mode * * @param pipeHandle pipe handle * @param buffer byte array to be written * @return >= 0 if 0 or more bytes written, -1 if error */ public int writeFile(long pipeHandle, byte[] buffer) { return writeFile0(pipeHandle, buffer, 0, buffer.length); } private void ensureDirectBuffer( ByteBuffer b) throws IOException { if (!b.isDirect()) { throw new IOException("ByteBuffer is not a DirectByteBuffer"); } } // native functions private native long createNamedPipe0(final String pipeName, int instances, int buffersize); private native long createEvent0(boolean manual, boolean initiallySignalled); private native void resetEvent0(long handle); private native void setEvent0(long handle); private native int getLastError0(); /** * Connect to a namedpipe client (native code) * * The eventHandle will be inserted into the OVERLAP struct by the native code * (Java can't do this as the OOVERLAP struct is opaque to Java) * * @param pipeHandle pipe handle * @param ooverlapped contiguous array used to store a Windows OVERLAPPED structure * @return return 0 if sucessfull, ERROR_IO_PENDING if still pending, or GetLastError() if failure */ private native int connectNamedPipe0(long pipeHandle, ByteBuffer ooverlapped); private native long openExistingNamedPipe0(final String pipeName); private native boolean disconnectNamedPipe0(long pipeHandle); private native long getNamedPipeClientProcessId0(long pipeHandle); private native boolean closeHandle0(long handle); private native int waitForMultipleObjects0(int n, long[] ehandles, boolean waitAll, int millis); private native int getOverlappedResult0(long pipeHandle, ByteBuffer ooverlapped, boolean wait); /** * Read from a file in overlapped mode (native code) * * The eventHandle will be inserted into the OVERLAP struct by the native code * (Java can't do this as the OOVERLAP struct is opaque to Java) * * @param pipeHandle pipe handle * @param ooverlapped contiguous array used to store a Windows OVERLAPPED structure * @param buffer byte buffer to be read into * @param bufsize max number of bytes to read * @return >= 0 if 0 ore more bytes read, -1 if pending IO, -2 if other error */ private native boolean readFileOverlapped0(long pipeHandle, ByteBuffer ooverlapped, ByteBuffer buffer, int position, int bufsize); /** * Write to a file in overlapped mode (native code) * * The eventHandle will be inserted into the OVERLAP struct by the native code * (Java can't do this as the OOVERLAP struct is opaque to Java) * * @param pipeHandle pipe handle * @param ooverlapped contiguous array used to store a Windows OVERLAPPED structure * @param buffer byte buffer to be written * @param bufsize number of bytes to write * @return true if successful */ private native boolean writeFileOverlapped0(long pipeHandle, ByteBuffer ooverlapped, ByteBuffer buffer, int position, int bufsize); /** * Cancel pending asynchronous IO * Will not cancel pending IO for this handle started on another thread * * @param pipeHandle handle with pending IO to cancel * @return false if fails */ public boolean cancelIO(long pipeHandle) { return cancelIo0(pipeHandle); } /** * Cancel pending asynchronous IO * Cancells all pending IO on all threads * * @param pipeHandle handle with pending IO to cancel * @return false if fails */ public boolean cancelAllIo(long pipeHandle, ByteBuffer ooverlapped) { return cancelIoEx0(pipeHandle, ooverlapped); } /** * Cancel pending asynchronous IO * Will not cancel pending IO for this handle started on another thread * * @param pipeHandle handle with pending IO to cancel * @return false if fails */ private native boolean cancelIo0(long pipeHandle); /** * Cancel pending asynchronous IO * Cancells all pending IO on all threads * * @param pipeHandle handle with pending IO to cancel * @return false if fails */ private native boolean cancelIoEx0(long pipeHandle, ByteBuffer ooverlapped); private native int readFile0(long pipeHandle, byte[] buffer, int position, int bufsize); private native int writeFile0(long pipeHandle, byte[] buffer, int position, int bufsize); private static native long getConstantWaitObject0(); private static native long getConstantInfinite0(); private static native int getConstantErrorIOPending0(); private static native int getConstantErrorIOIncomplete0(); private static native int getConstantErrorHandleEOF0(); private static native int getConstantErrorMoreData0(); private static native int getConstantErrorPipeBusy0(); private static native int getConstantInvalidHandle0(); private static native int getConstantErrorPipeConnected0(); private static native int getConstantErrorBrokenPipe0(); // bytebuffer maniuplation private native ByteBuffer createDirectBuffer0(int buffersize); private native ByteBuffer createDirectOverlapStruct0(long eHandle); private native void freeDirectBuffer0(final ByteBuffer byteBuffer); }