Class: Win32::Pipe

Inherits:
Object
  • Object
show all
Includes:
Windows::Error, Windows::File, Windows::Handle, Windows::Pipe, Windows::Synchronize
Defined in:
lib/win32/pipe.rb

Overview

The Pipe class is an abstract base class for the Pipe::Server and Pipe::Client classes. Do not use this directly.

Direct Known Subclasses

Client, Server

Defined Under Namespace

Classes: Client, Error, Server

Constant Summary collapse

VERSION =

The version of this library

'0.2.1'
PIPE_BUFFER_SIZE =

:nodoc:

512
PIPE_TIMEOUT =

:nodoc:

5000
WAIT =

Blocking mode is enabled

PIPE_WAIT
NOWAIT =

Nonblocking mode is enabled

PIPE_NOWAIT
ACCESS_DUPLEX =

The pipe is bi-directional. Both server and client processes can read from and write to the pipe.

PIPE_ACCESS_DUPLEX
ACCESS_INBOUND =

The flow of data in the pipe goes from client to server only.

PIPE_ACCESS_INBOUND
ACCESS_OUTBOUND =

The flow of data in the pipe goes from server to client only.

PIPE_ACCESS_OUTBOUND
TYPE_BYTE =

Data is written to the pipe as a stream of bytes.

PIPE_TYPE_BYTE
TYPE_MESSAGE =

Data is written to the pipe as a stream of messages.

PIPE_TYPE_MESSAGE
READMODE_BYTE =

Data is read from the pipe as a stream of bytes.

PIPE_READMODE_BYTE
READMODE_MESSAGE =

Data is read from the pipe as a stream of messages.

PIPE_READMODE_MESSAGE
FIRST_PIPE_INSTANCE =

All instances beyond the first will fail with access denied errors.

FILE_FLAG_FIRST_PIPE_INSTANCE
WRITE_THROUGH =

Functions do not return until the data is written across the network.

FILE_FLAG_WRITE_THROUGH
OVERLAPPED =

Overlapped mode enables asynchronous communication.

FILE_FLAG_OVERLAPPED
DEFAULT_PIPE_MODE =

The default pipe mode

NOWAIT
DEFAULT_OPEN_MODE =

The default open mode

FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, pipe_mode = DEFAULT_PIPE_MODE, open_mode = DEFAULT_OPEN_MODE) ⇒ Pipe

Abstract initializer for base class. This handles automatic prepending of ‘\.pipe' to each named pipe so that you don’t have to. Don’t use this directly. Add the full implementation in subclasses.

The default pipe mode is PIPE_WAIT.

The default open mode is FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH.



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/win32/pipe.rb', line 97

def initialize(name, pipe_mode = DEFAULT_PIPE_MODE, open_mode = DEFAULT_OPEN_MODE)
   @name = "\\\\.\\pipe\\" + name

   @pipe_mode = pipe_mode.nil? ? DEFAULT_PIPE_MODE : pipe_mode
   @open_mode = open_mode.nil? ? DEFAULT_OPEN_MODE : open_mode

   @pipe         = nil
   @pending_io   = false
   @buffer       = 0.chr * PIPE_BUFFER_SIZE
   @size         = 0
   @overlapped   = 0.chr * 20 # sizeof(OVERLAPPED)
   @transferred  = 0
   @asynchronous = false

   if open_mode & FILE_FLAG_OVERLAPPED > 0
      @asynchronous = true
   end

   if @asynchronous
      @event = CreateEvent(nil, true, true, nil)
      @overlapped[16, 4] = [@event].pack('L')
   end
end

Instance Attribute Details

#bufferObject (readonly)

The data still in the pipe’s buffer



72
73
74
# File 'lib/win32/pipe.rb', line 72

def buffer
  @buffer
end

#nameObject (readonly)

The full name of the pipe, e.g. “\\.\pipe\my_pipe”



81
82
83
# File 'lib/win32/pipe.rb', line 81

def name
  @name
end

#open_modeObject (readonly)

The pipe mode of the pipe.



84
85
86
# File 'lib/win32/pipe.rb', line 84

def open_mode
  @open_mode
end

#pipe_modeObject (readonly)

The open mode of the pipe.



87
88
89
# File 'lib/win32/pipe.rb', line 87

def pipe_mode
  @pipe_mode
end

#sizeObject (readonly) Also known as: length

The number of bytes to be written to the pipe.



75
76
77
# File 'lib/win32/pipe.rb', line 75

def size
  @size
end

#transferredObject (readonly)

The number of characters that are actually transferred over the pipe.



78
79
80
# File 'lib/win32/pipe.rb', line 78

def transferred
  @transferred
end

Instance Method Details

#asynchronous?Boolean

Returns whether or not the pipe is asynchronous.

Returns:

  • (Boolean)


140
141
142
# File 'lib/win32/pipe.rb', line 140

def asynchronous?
   @asynchronous
end

#closeObject

Closes the pipe.



128
129
130
# File 'lib/win32/pipe.rb', line 128

def close
   CloseHandle(@pipe)
end

#disconnectObject

Disconnects the pipe.



122
123
124
# File 'lib/win32/pipe.rb', line 122

def disconnect
   DisconnectNamedPipe(@pipe)
end

#pending?Boolean

Returns whether or not there is a pending IO operation on the pipe.

Returns:

  • (Boolean)


134
135
136
# File 'lib/win32/pipe.rb', line 134

def pending?
   @pending_io
end

#readObject

Reads data from the pipe. You can read data from either end of a named pipe.



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/win32/pipe.rb', line 147

def read
   bytes = [0].pack('L')
   @buffer = 0.chr * PIPE_BUFFER_SIZE
   
   if @asynchronous
      bool = ReadFile(@pipe, @buffer, @buffer.size, bytes, @overlapped)

      bytes_read = bytes.unpack('L').first

      if bool && bytes_read > 0
         @pending_io = false
         @buffer = @buffer[0, bytes_read]
         return true
      end

      error = GetLastError()
      if !bool && error == ERROR_IO_PENDING
         @pending_io = true
         return true
      end

      return false
   else
      unless ReadFile(@pipe, @buffer, @buffer.size, bytes, nil)
         raise Error, get_last_error
      end
   end
   
   @buffer.unpack("A*")
end

#wait(max_time = nil) ⇒ Object

Returns the pipe object if an event (such as a client connection) occurs within the max_time specified (in seconds). Otherwise, it returns false.



217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/win32/pipe.rb', line 217

def wait(max_time = nil)
   unless @asynchronous
      raise Error, 'cannot wait in synchronous (blocking) mode'
   end

   max_time = max_time ? max_time * 1000 : INFINITE

   wait = WaitForSingleObject(@event, max_time)

   if wait == WAIT_TIMEOUT
      return false
   else
      if wait != WAIT_OBJECT_0
         raise Error, get_last_error
      end
   end

   if @pending_io
      transferred = [0].pack('L')
      bool = GetOverlappedResult(@pipe, @overlapped, transferred, false)

      unless bool
         raise Error, get_last_error
      end

      @transferred = transferred.unpack('L')[0]
      @buffer = @buffer[0, @transferred]
   end

   self
end

#write(data) ⇒ Object

Writes ‘data’ to the pipe. You can write data to either end of a named pipe.



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/win32/pipe.rb', line 181

def write(data)
   @buffer = data
   @size   = data.size
   bytes   = [0].pack('L')

   if @asynchronous
      bool = WriteFile(@pipe, @buffer, @buffer.size, bytes, @overlapped)

      bytes_written = bytes.unpack('L').first

      if bool && bytes_written > 0
         @pending_io = false
         return true
      end

      error = GetLastError()

      if !bool && error == ERROR_IO_PENDING
         @pending_io = true
         return true
      end

      return false
   else
      unless WriteFile(@pipe, @buffer, @buffer.size, bytes, 0)
         raise Error, get_last_error
      end

      return true
   end
end