1 /*
2  * indchan.h
3  *
4  * Indirect I/O channel class.
5  *
6  * Portable Windows Library
7  *
8  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Portable Windows Library.
21  *
22  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23  *
24  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25  * All Rights Reserved.
26  *
27  * Contributor(s): ______________________________________.
28  *
29  * $Revision: 26933 $
30  * $Author: rjongbloed $
31  * $Date: 2012-02-02 21:17:20 -0600 (Thu, 02 Feb 2012) $
32  */
33 
34 #ifndef PTLIB_INDIRECTCHANNEL_H
35 #define PTLIB_INDIRECTCHANNEL_H
36 
37 #ifdef P_USE_PRAGMA
38 #pragma interface
39 #endif
40 
41 #include <ptlib/channel.h>
42 #include <ptlib/syncthrd.h>
43 
44 /**This is a channel that operates indirectly through another channel(s). This
45    allows for a protocol to operate through a "channel" mechanism and for its
46    low level byte exchange (Read and Write) to operate via a completely
47    different channel, eg TCP or Serial port etc.
48  */
49 class PIndirectChannel : public PChannel
50 {
51   PCLASSINFO(PIndirectChannel, PChannel);
52 
53   public:
54   /**@name Construction */
55   //@{
56     /**Create a new indirect channel without any channels to redirect to. If
57        an attempt to read or write is made before Open() is called the the
58        functions will assert.
59      */
60     PIndirectChannel();
61 
62     /// Close the indirect channel, deleting read/write channels if desired.
63     ~PIndirectChannel();
64   //@}
65 
66 
67   /**@name Overrides from class PObject */
68   //@{
69     /**Determine if the two objects refer to the same indirect channel. This
70        actually compares the channel pointers.
71 
72        @return
73        EqualTo if channel pointer identical.
74      */
75     Comparison Compare(
76       const PObject & obj   ///< Another indirect channel to compare against.
77     ) const;
78   //@}
79 
80 
81   /**@name Overrides from class PChannel */
82   //@{
83     /**Get the name of the channel. This is a combination of the channel
84        pointers names (or simply the channel pointers name if the read and
85        write channels are the same) or empty string if both null.
86 
87        @return
88        string for the channel names.
89      */
90     virtual PString GetName() const;
91 
92     /**Close the channel. This will detach itself from the read and write
93        channels and delete both of them if they are auto delete.
94 
95        @return
96        true if the channel is closed.
97      */
98     virtual PBoolean Close();
99 
100     /**Determine if the channel is currently open and read and write operations
101        can be executed on it. For example, in the <code>PFile</code> class it returns
102        if the file is currently open.
103 
104        @return
105        true if the channel is open.
106      */
107     virtual PBoolean IsOpen() const;
108 
109     /**Low level read from the channel. This function may block until the
110        requested number of characters were read or the read timeout was
111        reached. The GetLastReadCount() function returns the actual number
112        of bytes read.
113 
114        This will use the <code>readChannel</code> pointer to actually do the
115        read. If <code>readChannel</code> is null the this asserts.
116 
117        The GetErrorCode() function should be consulted after Read() returns
118        false to determine what caused the failure.
119 
120        @return
121        true indicates that at least one character was read from the channel.
122        false means no bytes were read due to timeout or some other I/O error.
123      */
124     virtual PBoolean Read(
125       void * buf,   ///< Pointer to a block of memory to receive the read bytes.
126       PINDEX len    ///< Maximum number of bytes to read into the buffer.
127     );
128 
129     /**Low level write to the channel. This function will block until the
130        requested number of characters are written or the write timeout is
131        reached. The GetLastWriteCount() function returns the actual number
132        of bytes written.
133 
134        This will use the <code>writeChannel</code> pointer to actually do the
135        write. If <code>writeChannel</code> is null the this asserts.
136 
137        The GetErrorCode() function should be consulted after Write() returns
138        false to determine what caused the failure.
139 
140        @return
141        true if at least len bytes were written to the channel.
142      */
143     virtual PBoolean Write(
144       const void * buf, ///< Pointer to a block of memory to write.
145       PINDEX len        ///< Number of bytes to write.
146     );
147 
148     /**Close one or both of the data streams associated with a channel.
149 
150        The behavour here is to pass the shutdown on to its read and write
151        channels.
152 
153        @return
154        true if the shutdown was successfully performed.
155      */
156     virtual PBoolean Shutdown(
157       ShutdownValue option   ///< Flag for shut down of read, write or both.
158     );
159 
160     /**Set local echo mode.
161        For some classes of channel, e.g. PConsoleChannel, data read by this
162        channel is automatically echoed. This disables the function so things
163        like password entry can work.
164 
165        Default behaviour does nothing and return true if the channel is open.
166       */
167     virtual bool SetLocalEcho(
168       bool localEcho
169     );
170 
171 
172     /**This function returns the eventual base channel for reading of a series
173        of indirect channels provided by descendents of <code>PIndirectChannel</code>.
174 
175        The behaviour for this function is to return "this".
176 
177        @return
178        Pointer to base I/O channel for the indirect channel.
179      */
180     virtual PChannel * GetBaseReadChannel() const;
181 
182     /**This function returns the eventual base channel for writing of a series
183        of indirect channels provided by descendents of <code>PIndirectChannel</code>.
184 
185        The behaviour for this function is to return "this".
186 
187        @return
188        Pointer to base I/O channel for the indirect channel.
189      */
190     virtual PChannel * GetBaseWriteChannel() const;
191 
192     /** Get error message description.
193         Return a string indicating the error message that may be displayed to
194        the user. The error for the last I/O operation in this object is used.
195       @return Operating System error description string.
196      */
197     virtual PString GetErrorText(
198       ErrorGroup group = NumErrorGroups   ///< Error group to get
199     ) const;
200   //@}
201 
202   /**@name Channel establish functions */
203   //@{
204     /**Set the channel for both read and write operations. This then checks
205        that they are open and then calls the OnOpen() virtual function. If
206        it in turn returns true then the Open() function returns success.
207 
208        @return
209        true if both channels are set, open and OnOpen() returns true.
210      */
211     PBoolean Open(
212       PChannel & channel   ///< Channel to be used for both read and write operations.
213     );
214 
215     /**Set the channel for both read and write operations. This then checks
216        that they are open and then calls the OnOpen() virtual function. If
217        it in turn returns true then the Open() function returns success.
218 
219        The channel pointed to by <code>channel</code> may be automatically deleted
220        when the PIndirectChannel is destroyed or a new subchannel opened.
221 
222        @return
223        true if both channels are set, open and OnOpen() returns true.
224      */
225     PBoolean Open(
226       PChannel * channel,      ///< Channel to be used for both read and write operations.
227       PBoolean autoDelete = true   ///< Automatically delete the channel
228     );
229 
230     /**Set the channel for both read and write operations. This then checks
231        that they are open and then calls the OnOpen() virtual function. If
232        it in turn returns true then the Open() function returns success.
233 
234        The channels pointed to by <code>readChannel</code> and <code>writeChannel</code> may be
235        automatically deleted when the PIndirectChannel is destroyed or a
236        new subchannel opened.
237 
238        @return
239        true if both channels are set, open and OnOpen() returns true.
240      */
241     PBoolean Open(
242       PChannel * readChannel,      ///< Channel to be used for both read operations.
243       PChannel * writeChannel,     ///< Channel to be used for both write operations.
244       PBoolean autoDeleteRead = true,  ///< Automatically delete the read channel
245       PBoolean autoDeleteWrite = true  ///< Automatically delete the write channel
246     );
247 
248     /**Get the channel used for read operations.
249 
250        @return
251        pointer to the read channel.
252      */
253     PChannel * GetReadChannel() const;
254 
255     /**Set the channel for read operations.
256 
257        @return
258        Returns true if both channels are set and are both open.
259      */
260     bool SetReadChannel(
261       PChannel * channel,         ///< Channel to be used for both read operations.
262       bool autoDelete = true,     ///< Automatically delete the channel
263       bool closeExisting = false  ///< Close (and auto-delete) the existing read channel
264     );
265 
266     /**Get the channel used for write operations.
267 
268        @return
269        pointer to the write channel.
270      */
271     PChannel * GetWriteChannel() const;
272 
273     /**Set the channel for read operations.
274 
275        @return
276        Returns true if both channels are set and are both open.
277     */
278     PBoolean SetWriteChannel(
279       PChannel * channel,         ///< Channel to be used for both read operations.
280       bool autoDelete = true,     ///< Automatically delete the channel
281       bool closeExisting = false  ///< Close (and auto-delete) the existing read channel
282     );
283   //@}
284 
285 
286   protected:
287     /**This callback is executed when the Open() function is called with
288        open channels. It may be used by descendent channels to do any
289        handshaking required by the protocol that channel embodies.
290 
291        The default behaviour is to simply return true.
292 
293        @return
294        Returns true if the protocol handshaking is successful.
295      */
296     virtual PBoolean OnOpen();
297 
298 
299   // Member variables
300     /// Channel for read operations.
301     PChannel * readChannel;
302 
303     /// Automatically delete read channel on destruction.
304     PBoolean readAutoDelete;
305 
306     /// Channel for write operations.
307     PChannel * writeChannel;
308 
309     /// Automatically delete write channel on destruction.
310     PBoolean writeAutoDelete;
311 
312     /// Race condition prevention on closing channel
313     PReadWriteMutex channelPointerMutex;
314 };
315 
316 
317 #endif // PTLIB_INDIRECTCHANNEL_H
318 
319 
320 // End Of File ///////////////////////////////////////////////////////////////
321