def connect(self, timeout=0, buf_sz=0): if self.transport == Pipe.Transport.ASYNCHRONOUS: if timeout == 0: event_timeout = w32ev.INFINITE stream = self.__getOverlappedStruct() # Asynchronous named pipes return immediately! status_code = w32p.ConnectNamedPipe( self.__hPipe, stream ) if status_code != werr.ERROR_IO_PENDING: raise PipeError( 'Failed to create unsynchronous named pipe connection!', 'status_code', status_code ) self.__waitForEvent(stream, event_timeout) else: status_code = w32p.ConnectNamedPipe(self.__hPipe, None) if status_code != 0: raise PipeError( 'Failed to create synchronous named pipe connection!', 'status_code', status_code ) return 0
def __waitForEvent(self, stream, event_timeout): # Asynchronous I/O operations may complete in the # blink of an eye giving the false impression that # it completed as a synchronous I/O. As such, we # have to wait for the event to be signaled by the # read operation. # This is also required if GetOverlappedResult does # not wait for data to become available (bWait is # set to False) otherwise it will complain that the # event handler is in a non-signaled state. event_code = w32ev.WaitForSingleObject( stream.hEvent, event_timeout ) if event_code == w32ev.WAIT_TIMEOUT: raise PipeTimeoutError( 'Connection timeout while awaiting pipe activity!', 'event_timeout', event_timeout, 'event_code', event_code ) elif event_code != w32ev.WAIT_OBJECT_0: raise PipeError( 'Unexpected pipe signal code event!', 'event_code', event_code )
def read(self, timeout=0, buf_sz=0): if self.transport == Pipe.Transport.ASYNCHRONOUS: if timeout is None: evTimeout = 50 # 50ms is the default value per MSDN docs. elif int(timeout) == 0: evTimeout = 50 # 50ms is the default value per MSDN docs. else: evTimeout = int(timeout) stream = self._getOverlappedStruct() if buf_sz <= 0: buf_sz = 2048 ov_buf = w32f.AllocateReadBuffer(buf_sz) pipe_data = '' while True: try: pipe_status, pipe_buffer = w32f.ReadFile( self.__hPipe, ov_buf, stream ) except WinT.error, e: if e.args[0] == werr.ERROR_BROKEN_PIPE: return 1, stream.Offset, pipe_data else: raise if pipe_status == 0 or \ pipe_status == werr.ERROR_IO_PENDING: #TODO: Return stream and then prompt user to fetch data. if pipe_status == werr.ERROR_IO_PENDING: self.__waitForEvent(stream, evTimeout) try: read_bytes = w32f.GetOverlappedResult( self.__hPipe, stream, False ) except WinT.error, e: if e.args[0] == werr.ERROR_MORE_DATA: ov_buf = self.__expandBufferPipe(buf_sz) stream.Offset += len(pipe_buffer) pipe_data += pipe_buffer continue elif e.args[0] == werr.ERROR_BROKEN_PIPE: return 1, stream.Offset, pipe_data else: raise elif pipe_status == werr.ERROR_MORE_DATA: ov_buf = self.__expandBufferPipe(buf_sz) stream.Offset += len(pipe_buffer) pipe_data += pipe_buffer continue else: raise PipeError( 'Pipe encountered a fatal error!', 'error_code', w32api.GetLastError() ) stream.Offset += read_bytes pipe_data += pipe_buffer[:read_bytes] if read_bytes < len(pipe_buffer): return 0, stream.Offset, pipe_data
def _listen(self, policy=POLICY.RW, repeat=True): status_code = self.connect() if status_code == 0: pipe_status, pipe_bytes, pipe_content = self.read() self.close() else: raise PipeError( 'Pipe encountered an error while attempting a connection!', 'status_code', status_code) return status_code, pipe_status, pipe_bytes, pipe_content
def connect(self, timeout=0, buf_sz=0, ev_aware=True): if self.transport == Pipe.Transport.ASYNCHRONOUS: if int(timeout) == 0: evTimeout = w32ev.INFINITE else: evTimeout = int(timeout) stream = self._getOverlappedStruct() # Asynchronous named pipes return immediately! status_code = w32p.ConnectNamedPipe( self.__hPipe, stream ) # From the MSDN docs: # https://msdn.microsoft.com/en-us/library/windows/desktop/aa365146(v=vs.85).aspx # If a client connects before the function is called (i.e. # the timeframe between CreateNamedPipe and ConnectNamedPipe, the # latter function returns zero and GetLastError returns # ERROR_PIPE_CONNECTED. if status_code == werr.ERROR_PIPE_CONNECTED: w32ev.SetEvent(stream.hEvent) if ev_aware: return stream elif status_code != werr.ERROR_IO_PENDING: raise PipeError( 'Failed to create unsynchronous named pipe connection!', 'status_code', status_code ) else: if ev_aware: self.__waitForEvent(stream, evTimeout) else: return stream else: status_code = w32p.ConnectNamedPipe(self.__hPipe, None) if status_code != 0: raise PipeError( 'Failed to create synchronous named pipe connection!', 'status_code', status_code ) return 0
def _listen(self, timeout=0, policy=POLICY.RW): status_code = self.connect() if status_code == 0: status_code, written_bytes = self.write("Hello CRAPI client! :)", timeout=timeout) print("Payload status code (W): ", end="") print(status_code) print("# of bytes written (W): ", end="") print(written_bytes) pipe_status, pipe_bytes, pipe_content = self.read(timeout=timeout) self.close() else: raise PipeError( 'Pipe encountered an error while attempting a connection!', 'status_code', status_code) return status_code, pipe_status, pipe_bytes, pipe_content