win32-pipe 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,33 +1,33 @@
1
- #########################################################################
2
- # example_server.rb
3
- #
4
- # A simple named pipe server. Start this up in its own terminal window.
5
- # You may have to use the task manager to kill it if you don't connect
6
- # with the test client program.
7
- #
8
- # You can start this server with the 'rake example_server' task. Modify
9
- # this code as you see fit.
10
- #########################################################################
11
- require 'win32/pipe'
12
- include Win32
13
-
14
- Thread.new { loop { sleep 0.01 } } # Allow Ctrl-C
15
-
16
- puts "VERSION: " + Pipe::VERSION
17
-
18
- # Block form
19
- Pipe::Server.new('foo') do |pipe|
20
- pipe.connect
21
- data = pipe.read
22
- puts "Got [#{data}]"
23
- pipe.write "Thanks for the data!"
24
- end
25
-
26
- # Non-block form
27
- #pserver = Pipe::Server.new('foo')
28
- #pserver.connect # put server in wait connect
29
- #data = pserver.read
30
- #puts "Got [#{data}]"
31
- #pserver.write("Thanks for the data!")
32
- #pserver.disconnect
1
+ #########################################################################
2
+ # example_server.rb
3
+ #
4
+ # A simple named pipe server. Start this up in its own terminal window.
5
+ # You may have to use the task manager to kill it if you don't connect
6
+ # with the test client program.
7
+ #
8
+ # You can start this server with the 'rake example_server' task. Modify
9
+ # this code as you see fit.
10
+ #########################################################################
11
+ require 'win32/pipe'
12
+ include Win32
13
+
14
+ Thread.new { loop { sleep 0.01 } } # Allow Ctrl-C
15
+
16
+ puts "VERSION: " + Pipe::VERSION
17
+
18
+ # Block form
19
+ Pipe::Server.new('foo') do |pipe|
20
+ pipe.connect
21
+ data = pipe.read
22
+ puts "Got [#{data}]"
23
+ pipe.write "Thanks for the data!"
24
+ end
25
+
26
+ # Non-block form
27
+ #pserver = Pipe::Server.new('foo')
28
+ #pserver.connect # put server in wait connect
29
+ #data = pserver.read
30
+ #puts "Got [#{data}]"
31
+ #pserver.write("Thanks for the data!")
32
+ #pserver.disconnect
33
33
  #pserver.close
@@ -1,100 +1,100 @@
1
- #######################################################################
2
- # example_server_async.rb
3
- #
4
- # A simple, asynchronous named pipe server. Start this up in its own
5
- # terminal window. You can run this program via the
6
- # 'rake example_async_server' task.
7
- #######################################################################
8
- require 'win32/pipe'
9
- include Win32
10
-
11
- puts "VERSION: " + Pipe::VERSION
12
-
13
- Thread.new { loop { sleep 0.01 } } # Allow Ctrl-C
14
-
15
- CONNECTING_STATE = 0
16
- READING_STATE = 1
17
- WRITING_STATE = 2
18
-
19
- class MyPipe < Pipe::Server
20
- def connected
21
- puts "connected"
22
- @state = READING_STATE
23
- end
24
-
25
- def read_complete
26
- puts "read_complete"
27
- puts "Got [#{buffer}]"
28
- @state = WRITING_STATE
29
- end
30
-
31
- def write_complete
32
- puts "write_complete"
33
- disconnect
34
- @state = CONNECTING_STATE
35
- end
36
-
37
- def reconnect
38
- disconnect
39
- mainloop
40
- end
41
-
42
- def mainloop
43
- @state = CONNECTING_STATE
44
- while true
45
- if wait(1) # wait for 1 second
46
- if pending? # IO is pending
47
- case @state
48
- when CONNECTING_STATE
49
- connected
50
- when READING_STATE
51
- if transferred == 0
52
- reconnect
53
- break
54
- end
55
- read_complete
56
- when WRITING_STATE
57
- if transferred != length
58
- reconnect
59
- break
60
- end
61
- write_complete
62
- end
63
- end
64
-
65
- case @state
66
- when CONNECTING_STATE
67
- if connect
68
- connected
69
- end
70
- when READING_STATE
71
- if read
72
- if !pending?
73
- read_complete
74
- end
75
- else
76
- reconnect
77
- end
78
- when WRITING_STATE
79
- if write("Thanks for the data!")
80
- if not pending?
81
- write_complete
82
- end
83
- else
84
- reconnect
85
- break
86
- end
87
- end
88
- end
89
-
90
- sleep(1)
91
- puts "pipe server is running"
92
- end
93
- end
94
- end
95
-
96
- flags = Pipe::ACCESS_DUPLEX | Pipe::OVERLAPPED
97
-
98
- MyPipe.new('foo', 0, flags) do |pipe|
99
- pipe.mainloop
100
- end
1
+ #######################################################################
2
+ # example_server_async.rb
3
+ #
4
+ # A simple, asynchronous named pipe server. Start this up in its own
5
+ # terminal window. You can run this program via the
6
+ # 'rake example_async_server' task.
7
+ #######################################################################
8
+ require 'win32/pipe'
9
+ include Win32
10
+
11
+ puts "VERSION: " + Pipe::VERSION
12
+
13
+ Thread.new { loop { sleep 0.01 } } # Allow Ctrl-C
14
+
15
+ CONNECTING_STATE = 0
16
+ READING_STATE = 1
17
+ WRITING_STATE = 2
18
+
19
+ class MyPipe < Pipe::Server
20
+ def connected
21
+ puts "connected"
22
+ @state = READING_STATE
23
+ end
24
+
25
+ def read_complete
26
+ puts "read_complete"
27
+ puts "Got [#{buffer}]"
28
+ @state = WRITING_STATE
29
+ end
30
+
31
+ def write_complete
32
+ puts "write_complete"
33
+ disconnect
34
+ @state = CONNECTING_STATE
35
+ end
36
+
37
+ def reconnect
38
+ disconnect
39
+ mainloop
40
+ end
41
+
42
+ def mainloop
43
+ @state = CONNECTING_STATE
44
+ while true
45
+ if wait(1) # wait for 1 second
46
+ if pending? # IO is pending
47
+ case @state
48
+ when CONNECTING_STATE
49
+ connected
50
+ when READING_STATE
51
+ if transferred == 0
52
+ reconnect
53
+ break
54
+ end
55
+ read_complete
56
+ when WRITING_STATE
57
+ if transferred != length
58
+ reconnect
59
+ break
60
+ end
61
+ write_complete
62
+ end
63
+ end
64
+
65
+ case @state
66
+ when CONNECTING_STATE
67
+ if connect
68
+ connected
69
+ end
70
+ when READING_STATE
71
+ if read
72
+ if !pending?
73
+ read_complete
74
+ end
75
+ else
76
+ reconnect
77
+ end
78
+ when WRITING_STATE
79
+ if write("Thanks for the data!")
80
+ if not pending?
81
+ write_complete
82
+ end
83
+ else
84
+ reconnect
85
+ break
86
+ end
87
+ end
88
+ end
89
+
90
+ sleep(1)
91
+ puts "pipe server is running"
92
+ end
93
+ end
94
+ end
95
+
96
+ flags = Pipe::ACCESS_DUPLEX | Pipe::OVERLAPPED
97
+
98
+ MyPipe.new('foo', 0, flags) do |pipe|
99
+ pipe.mainloop
100
+ end
data/lib/win32/pipe.rb CHANGED
@@ -1,254 +1,251 @@
1
- require 'windows/pipe'
2
- require 'windows/synchronize'
3
- require 'windows/handle'
4
- require 'windows/file'
5
- require 'windows/error'
6
-
7
- # The Win32 module serves as a namespace only.
8
- module Win32
9
- # The Pipe class is an abstract base class for the Pipe::Server and
10
- # Pipe::Client classes. Do not use this directly.
11
- #
12
- class Pipe
13
- include Windows::Pipe
14
- include Windows::Synchronize
15
- include Windows::Handle
16
- include Windows::File
17
- include Windows::Error
18
-
19
- # Error typically raised if any of the Pipe methods fail.
20
- class Error < StandardError; end
21
-
22
- # The version of this library
23
- VERSION = '0.2.2'
24
-
25
- PIPE_BUFFER_SIZE = 512 #:nodoc:
26
- PIPE_TIMEOUT = 5000 #:nodoc:
27
-
28
- # Blocking mode is enabled
29
- WAIT = PIPE_WAIT
30
-
31
- # Nonblocking mode is enabled
32
- NOWAIT = PIPE_NOWAIT
33
-
34
- # The pipe is bi-directional. Both server and client processes can read
35
- # from and write to the pipe.
36
- ACCESS_DUPLEX = PIPE_ACCESS_DUPLEX
37
-
38
- # The flow of data in the pipe goes from client to server only.
39
- ACCESS_INBOUND = PIPE_ACCESS_INBOUND
40
-
41
- # The flow of data in the pipe goes from server to client only.
42
- ACCESS_OUTBOUND = PIPE_ACCESS_OUTBOUND
43
-
44
- # Data is written to the pipe as a stream of bytes.
45
- TYPE_BYTE = PIPE_TYPE_BYTE
46
-
47
- # Data is written to the pipe as a stream of messages.
48
- TYPE_MESSAGE = PIPE_TYPE_MESSAGE
49
-
50
- # Data is read from the pipe as a stream of bytes.
51
- READMODE_BYTE = PIPE_READMODE_BYTE
52
-
53
- # Data is read from the pipe as a stream of messages.
54
- READMODE_MESSAGE = PIPE_READMODE_MESSAGE
55
-
56
- # All instances beyond the first will fail with access denied errors.
57
- FIRST_PIPE_INSTANCE = FILE_FLAG_FIRST_PIPE_INSTANCE
58
-
59
- # Functions do not return until the data is written across the network.
60
- WRITE_THROUGH = FILE_FLAG_WRITE_THROUGH
61
-
62
- # Overlapped mode enables asynchronous communication.
63
- OVERLAPPED = FILE_FLAG_OVERLAPPED
64
-
65
- # The default pipe mode
66
- DEFAULT_PIPE_MODE = NOWAIT
67
-
68
- # The default open mode
69
- DEFAULT_OPEN_MODE = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH
70
-
71
- # The data still in the pipe's buffer
72
- attr_reader :buffer
73
-
74
- # The number of bytes to be written to the pipe.
75
- attr_reader :size
76
-
77
- # The number of characters that are actually transferred over the pipe.
78
- attr_reader :transferred
79
-
80
- # The full name of the pipe, e.g. "\\\\.\\pipe\\my_pipe"
81
- attr_reader :name
82
-
83
- # The pipe mode of the pipe.
84
- attr_reader :open_mode
85
-
86
- # The open mode of the pipe.
87
- attr_reader :pipe_mode
88
-
89
- # Abstract initializer for base class. This handles automatic prepending
90
- # of '\\.\pipe\' to each named pipe so that you don't have to. Don't
91
- # use this directly. Add the full implementation in subclasses.
92
- #
93
- # The default pipe mode is PIPE_WAIT.
94
- #
95
- # The default open mode is FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH.
96
- #
97
- def initialize(name, pipe_mode = DEFAULT_PIPE_MODE, open_mode = DEFAULT_OPEN_MODE)
98
- @name = "\\\\.\\pipe\\" + name
99
-
100
- @pipe_mode = pipe_mode.nil? ? DEFAULT_PIPE_MODE : pipe_mode
101
- @open_mode = open_mode.nil? ? DEFAULT_OPEN_MODE : open_mode
102
-
103
- @pipe = nil
104
- @pending_io = false
105
- @buffer = 0.chr * PIPE_BUFFER_SIZE
106
- @size = 0
107
- @overlapped = 0.chr * 20 # sizeof(OVERLAPPED)
108
- @transferred = 0
109
- @asynchronous = false
110
-
111
- if open_mode & FILE_FLAG_OVERLAPPED > 0
112
- @asynchronous = true
113
- end
114
-
115
- if @asynchronous
116
- @event = CreateEvent(nil, true, true, nil)
117
- @overlapped[16, 4] = [@event].pack('L')
118
- end
119
- end
120
-
121
- # Disconnects the pipe.
122
- def disconnect
123
- DisconnectNamedPipe(@pipe)
124
- end
125
-
126
- # Closes the pipe.
127
- #
128
- def close
129
- CloseHandle(@pipe)
130
- end
131
-
132
- # Returns whether or not there is a pending IO operation on the pipe.
133
- #
134
- def pending?
135
- @pending_io
136
- end
137
-
138
- # Returns whether or not the pipe is asynchronous.
139
- #
140
- def asynchronous?
141
- @asynchronous
142
- end
143
-
144
- # Reads data from the pipe. You can read data from either end of a named
145
- # pipe.
146
- #
147
- def read
148
- bytes = [0].pack('L')
149
- @buffer = 0.chr * PIPE_BUFFER_SIZE
150
-
151
- if @asynchronous
152
- bool = ReadFile(@pipe, @buffer, @buffer.size, bytes, @overlapped)
153
-
154
- bytes_read = bytes.unpack('L').first
155
-
156
- if bool && bytes_read > 0
157
- @pending_io = false
158
- @buffer = @buffer[0, bytes_read]
159
- return true
160
- end
161
-
162
- error = GetLastError()
163
- if !bool && error == ERROR_IO_PENDING
164
- @pending_io = true
165
- return true
166
- end
167
-
168
- return false
169
- else
170
- unless ReadFile(@pipe, @buffer, @buffer.size, bytes, nil)
171
- raise Error, get_last_error
172
- end
173
- end
174
-
175
- @buffer.unpack("A*")
176
- end
177
-
178
- # Writes 'data' to the pipe. You can write data to either end of a
179
- # named pipe.
180
- #
181
- def write(data)
182
- @buffer = data
183
- @size = data.size
184
- bytes = [0].pack('L')
185
-
186
- if @asynchronous
187
- bool = WriteFile(@pipe, @buffer, @buffer.size, bytes, @overlapped)
188
-
189
- bytes_written = bytes.unpack('L').first
190
-
191
- if bool && bytes_written > 0
192
- @pending_io = false
193
- return true
194
- end
195
-
196
- error = GetLastError()
197
-
198
- if !bool && error == ERROR_IO_PENDING
199
- @pending_io = true
200
- return true
201
- end
202
-
203
- return false
204
- else
205
- unless WriteFile(@pipe, @buffer, @buffer.size, bytes, 0)
206
- raise Error, get_last_error
207
- end
208
-
209
- return true
210
- end
211
- end
212
-
213
- # Returns the pipe object if an event (such as a client connection)
214
- # occurs within the +max_time+ specified (in seconds). Otherwise, it
215
- # returns false.
216
- #
217
- def wait(max_time = nil)
218
- unless @asynchronous
219
- raise Error, 'cannot wait in synchronous (blocking) mode'
220
- end
221
-
222
- max_time = max_time ? max_time * 1000 : INFINITE
223
-
224
- wait = WaitForSingleObject(@event, max_time)
225
-
226
- if wait == WAIT_TIMEOUT
227
- return false
228
- else
229
- if wait != WAIT_OBJECT_0
230
- raise Error, get_last_error
231
- end
232
- end
233
-
234
- if @pending_io
235
- transferred = [0].pack('L')
236
- bool = GetOverlappedResult(@pipe, @overlapped, transferred, false)
237
-
238
- unless bool
239
- raise Error, get_last_error
240
- end
241
-
242
- @transferred = transferred.unpack('L')[0]
243
- @buffer = @buffer[0, @transferred]
244
- end
245
-
246
- self
247
- end
248
-
249
- alias length size
250
- end
251
- end
252
-
253
- require 'win32/pipe/server'
254
- require 'win32/pipe/client'
1
+ require File.join(File.dirname(__FILE__), 'pipe', 'windows', 'constants')
2
+ require File.join(File.dirname(__FILE__), 'pipe', 'windows', 'functions')
3
+
4
+ # The Win32 module serves as a namespace only.
5
+ module Win32
6
+ # The Pipe class is an abstract base class for the Pipe::Server and
7
+ # Pipe::Client classes. Do not use this directly.
8
+ #
9
+ class Pipe
10
+ include Windows::Constants
11
+ include Windows::Functions
12
+
13
+ # Error raised when anything other than a SystemCallError occurs.
14
+ class Error < StandardError; end
15
+
16
+ # The version of this library
17
+ VERSION = '0.3.0'
18
+
19
+ PIPE_BUFFER_SIZE = 512 #:nodoc:
20
+ PIPE_TIMEOUT = 5000 #:nodoc:
21
+
22
+ # Blocking mode is enabled
23
+ WAIT = PIPE_WAIT
24
+
25
+ # Nonblocking mode is enabled
26
+ NOWAIT = PIPE_NOWAIT
27
+
28
+ # The pipe is bi-directional. Both server and client processes can read
29
+ # from and write to the pipe.
30
+ ACCESS_DUPLEX = PIPE_ACCESS_DUPLEX
31
+
32
+ # The flow of data in the pipe goes from client to server only.
33
+ ACCESS_INBOUND = PIPE_ACCESS_INBOUND
34
+
35
+ # The flow of data in the pipe goes from server to client only.
36
+ ACCESS_OUTBOUND = PIPE_ACCESS_OUTBOUND
37
+
38
+ # Data is written to the pipe as a stream of bytes.
39
+ TYPE_BYTE = PIPE_TYPE_BYTE
40
+
41
+ # Data is written to the pipe as a stream of messages.
42
+ TYPE_MESSAGE = PIPE_TYPE_MESSAGE
43
+
44
+ # Data is read from the pipe as a stream of bytes.
45
+ READMODE_BYTE = PIPE_READMODE_BYTE
46
+
47
+ # Data is read from the pipe as a stream of messages.
48
+ READMODE_MESSAGE = PIPE_READMODE_MESSAGE
49
+
50
+ # All instances beyond the first will fail with access denied errors.
51
+ FIRST_PIPE_INSTANCE = FILE_FLAG_FIRST_PIPE_INSTANCE
52
+
53
+ # Functions do not return until the data is written across the network.
54
+ WRITE_THROUGH = FILE_FLAG_WRITE_THROUGH
55
+
56
+ # Overlapped mode enables asynchronous communication.
57
+ OVERLAPPED = FILE_FLAG_OVERLAPPED
58
+
59
+ # The default pipe mode
60
+ DEFAULT_PIPE_MODE = NOWAIT
61
+
62
+ # The default open mode
63
+ DEFAULT_OPEN_MODE = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH
64
+
65
+ # The data still in the pipe's buffer
66
+ attr_reader :buffer
67
+
68
+ # The number of bytes to be written to the pipe.
69
+ attr_reader :size
70
+
71
+ # The number of characters that are actually transferred over the pipe.
72
+ attr_reader :transferred
73
+
74
+ # The full name of the pipe, e.g. "\\\\.\\pipe\\my_pipe"
75
+ attr_reader :name
76
+
77
+ # The pipe mode of the pipe.
78
+ attr_reader :open_mode
79
+
80
+ # The open mode of the pipe.
81
+ attr_reader :pipe_mode
82
+
83
+ # Abstract initializer for base class. This handles automatic prepending
84
+ # of '\\.\pipe\' to each named pipe so that you don't have to. Don't
85
+ # use this directly. Add the full implementation in subclasses.
86
+ #
87
+ # The default pipe mode is PIPE_WAIT.
88
+ #
89
+ # The default open mode is FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH.
90
+ #
91
+ def initialize(name, pipe_mode = DEFAULT_PIPE_MODE, open_mode = DEFAULT_OPEN_MODE)
92
+ @name = "\\\\.\\pipe\\" + name
93
+
94
+ @pipe_mode = pipe_mode.nil? ? DEFAULT_PIPE_MODE : pipe_mode
95
+ @open_mode = open_mode.nil? ? DEFAULT_OPEN_MODE : open_mode
96
+
97
+ @pipe = nil
98
+ @pending_io = false
99
+ @buffer = 0.chr * PIPE_BUFFER_SIZE
100
+ @size = 0
101
+ @overlapped = 0.chr * 20 # sizeof(OVERLAPPED)
102
+ @transferred = 0
103
+ @asynchronous = false
104
+
105
+ if open_mode & FILE_FLAG_OVERLAPPED > 0
106
+ @asynchronous = true
107
+ end
108
+
109
+ if @asynchronous
110
+ @event = CreateEvent(nil, true, true, nil)
111
+ @overlapped[16, 4] = [@event].pack('L')
112
+ end
113
+ end
114
+
115
+ # Disconnects the pipe.
116
+ def disconnect
117
+ DisconnectNamedPipe(@pipe) if @pipe
118
+ end
119
+
120
+ # Closes the pipe.
121
+ #
122
+ def close
123
+ CloseHandle(@pipe) if @pipe
124
+ end
125
+
126
+ # Returns whether or not there is a pending IO operation on the pipe.
127
+ #
128
+ def pending?
129
+ @pending_io
130
+ end
131
+
132
+ # Returns whether or not the pipe is asynchronous.
133
+ #
134
+ def asynchronous?
135
+ @asynchronous
136
+ end
137
+
138
+ # Reads data from the pipe. You can read data from either end of a named
139
+ # pipe.
140
+ #
141
+ def read
142
+ bytes = FFI::MemoryPointer.new(:ulong)
143
+ @buffer = 0.chr * PIPE_BUFFER_SIZE
144
+
145
+ raise Error, "no pipe created" unless @pipe
146
+
147
+ if @asynchronous
148
+ bool = ReadFile(@pipe, @buffer, @buffer.size, bytes, @overlapped)
149
+ error = GetLastError()
150
+
151
+ bytes_read = bytes.read_ulong
152
+
153
+ if bool && bytes_read > 0
154
+ @pending_io = false
155
+ @buffer = @buffer[0, bytes_read]
156
+ return true
157
+ end
158
+
159
+ if !bool && error == ERROR_IO_PENDING
160
+ @pending_io = true
161
+ return true
162
+ end
163
+
164
+ return false
165
+ else
166
+ unless ReadFile(@pipe, @buffer, @buffer.size, bytes, nil)
167
+ raise SystemCallError.new("ReadFile", FFI.errno)
168
+ end
169
+ end
170
+
171
+ @buffer.unpack("A*")
172
+ end
173
+
174
+ # Writes 'data' to the pipe. You can write data to either end of a
175
+ # named pipe.
176
+ #
177
+ def write(data)
178
+ @buffer = data
179
+ @size = data.size
180
+ bytes = FFI::MemoryPointer.new(:ulong)
181
+
182
+ raise Error, "no pipe created" unless @pipe
183
+
184
+ if @asynchronous
185
+ bool = WriteFile(@pipe, @buffer, @buffer.size, bytes, @overlapped)
186
+ error = GetLastError()
187
+
188
+ bytes_written = bytes.read_ulong
189
+
190
+ if bool && bytes_written > 0
191
+ @pending_io = false
192
+ return true
193
+ end
194
+
195
+ if !bool && error == ERROR_IO_PENDING
196
+ @pending_io = true
197
+ return true
198
+ end
199
+
200
+ return false
201
+ else
202
+ unless WriteFile(@pipe, @buffer, @buffer.size, bytes, nil)
203
+ raise SystemCallError.new("WriteFile", FFI.errno)
204
+ end
205
+
206
+ return true
207
+ end
208
+ end
209
+
210
+ # Returns the pipe object if an event (such as a client connection)
211
+ # occurs within the +max_time+ specified (in seconds). Otherwise, it
212
+ # returns false.
213
+ #
214
+ def wait(max_time = nil)
215
+ unless @asynchronous
216
+ raise Error, 'cannot wait in synchronous (blocking) mode'
217
+ end
218
+
219
+ max_time = max_time ? max_time * 1000 : INFINITE
220
+
221
+ wait = WaitForSingleObject(@event, max_time)
222
+
223
+ if wait == WAIT_TIMEOUT
224
+ return false
225
+ else
226
+ if wait != WAIT_OBJECT_0
227
+ raise SystemCallError.new("WaitForSingleObject", FFI.errno)
228
+ end
229
+ end
230
+
231
+ if @pending_io
232
+ transferred = FFI::MemoryPointer.new(:ulong)
233
+ bool = GetOverlappedResult(@pipe, @overlapped, transferred, false)
234
+
235
+ unless bool
236
+ raise SystemCallError.new("GetOverlappedResult", FFI.errno)
237
+ end
238
+
239
+ @transferred = transferred.read_ulong
240
+ @buffer = @buffer[0, @transferred]
241
+ end
242
+
243
+ self
244
+ end
245
+
246
+ alias length size
247
+ end
248
+ end
249
+
250
+ require File.join(File.dirname(__FILE__), 'pipe', 'server')
251
+ require File.join(File.dirname(__FILE__), 'pipe', 'client')