Source code for vsi.windows.named_pipes

#Can this be replaced with multiprocessing.connections.PipeListener, and PipeClient?!

#based off of http://code.activestate.com/lists/python-list/446422/

from ctypes import *

PIPE_ACCESS_DUPLEX = 0x3
PIPE_TYPE_MESSAGE = 0x4
PIPE_READMODE_MESSAGE = 0x2
PIPE_WAIT = 0
PIPE_UNLIMITED_INSTANCES = 255
BUFSIZE = 4096
NMPWAIT_USE_DEFAULT_WAIT = 0
INVALID_HANDLE_VALUE = -1
ERROR_PIPE_CONNECTED = 535

GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
OPEN_EXISTING = 0x3
PIPE_READMODE_MESSAGE = 0x2
ERROR_PIPE_BUSY = 231
ERROR_MORE_DATA = 234

PIPE_PREFIX=r'\\.\pipe'+'\\'

[docs]class PipeException(Exception): pass
[docs]def open(name, server=False): ''' Helper open function Parameters ---------- name : str Returns ------- :class:`Pipe` The pipe Give it the look and feel of python's open command ''' pipe = Pipe(name, server) return pipe
[docs]class Pipe(object): ''' Windows Named Pipe class similar to File objects ''' def __init__(self, name, server=False): self.server = server self.name = PIPE_PREFIX+name self.open()
[docs] def open(self): """ Raises ------ PipeException For an invalid handle value PipeException Could not connect to the named pipe PipeException Error pipe busy PipeException SetNamedPipeHandleState failed """ if self.server: self.hPipe = windll.kernel32.CreateNamedPipeA(self.name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, NMPWAIT_USE_DEFAULT_WAIT, None) if (self.hPipe == INVALID_HANDLE_VALUE): raise PipeException('Invalid Handle Value') fConnected = windll.kernel32.ConnectNamedPipe(self.hPipe, None) if ((fConnected == 0) and (windll.kernel32.GetLastError() == ERROR_PIPE_CONNECTED)): fConnected = 1 if fConnected != 1: self.close() raise PipeException("Could not connect to the Named Pipe") else: self.hPipe = windll.kernel32.CreateFileA(self.name, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, 0, None) if (self.hPipe == INVALID_HANDLE_VALUE): if (windll.kernel32.GetLastError() != ERROR_PIPE_BUSY): raise PipeException('Error Pipe Busy') else: raise PipeException('Invalid Handle Value') dwMode = c_ulong(PIPE_READMODE_MESSAGE) fSuccess = windll.kernel32.SetNamedPipeHandleState(self.hPipe, byref(dwMode), None, None) if (not fSuccess): raise PipeException('SetNamedPipeHandleState failed')
[docs] def read(self, bufferSize=4096): ''' Read up to bufferSize bytes ''' chBuf = create_string_buffer(bufferSize) cbRead = c_ulong(0) fSuccess = windll.kernel32.ReadFile(self.hPipe, chBuf, bufferSize, byref(cbRead), None) if fSuccess == 1 or windll.kernel32.GetLastError() == ERROR_MORE_DATA: #ERROR_MORE_DATA is only important in message mode, currently only using #byte mode return chBuf.value
[docs] @staticmethod def wait_for(name, timeout__ms): """ Parameters ---------- name : str timeout__ms : int The timeout in milliseconcds Returns ------- bool """ return windll.kernel32.WaitNamedPipeA(PIPE_PREFIX+name, timeout__ms)
[docs] def disconnect(self): ''' Send disconnect to client, forcing them to disconnect from the pipe ''' windll.kernel32.DisconnectNamedPipe(self.hPipe)
[docs] def write(self, message): """ Parameters ---------- message : str The message """ cbWritten = c_ulong(0) fSuccess = windll.kernel32.WriteFile(self.hPipe, c_char_p(message), len(message), byref(cbWritten), None) if not fSuccess: return None # if len(message) != cbWritten.value: # raise PipeException('Number of byte written does not match string length') return cbWritten.value
[docs] def close(self): windll.kernel32.CloseHandle(self.hPipe)