blob: 9645356920e4742078df468ac44f4678334d9bf6 [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
2//
3// This file is part of GNU uCommon C++.
4//
5// GNU uCommon C++ is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published
7// by the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// GNU uCommon C++ is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * Any ucommon streaming classes that are built from std::streamio facilities
20 * and that support ANSI C++ stream operators.
21 * @file ucommon/stream.h
22 */
23
24#if defined(OLD_STDCPP) || defined(NEW_STDCPP)
25#ifndef _UCOMMON_STREAM_H_
26#define _UCOMMON_STREAM_H_
27
28#ifndef _UCOMMON_CONFIG_H
29#include <ucommon/platform.h>
30#endif
31
32#ifndef _UCOMMON_PROTOCOLS_H_
33#include <ucommon/protocols.h>
34#endif
35
36#ifndef _UCOMMON_THREAD_H_
37#include <ucommon/thread.h>
38#endif
39
40#ifndef _UCOMMON_SOCKET_H_
41#include <ucommon/socket.h>
42#endif
43
44#ifndef _UCOMMON_FSYS_H_
45#include <ucommon/fsys.h>
46#endif
47
48#ifndef _UCOMMON_SHELL_H_
49#include <ucommon/shell.h>
50#endif
51
52#include <iostream>
53
54NAMESPACE_UCOMMON
55
56/**
57 * Common stream buffer for std C++ i/o classes. This both binds the
58 * character protocol to iostream and offers a common base class for all
59 * other c++ stdlib based streaming classes.
60 * @author David Sugar <dyfet@gnutelephony.org>
61 */
62class __EXPORT StreamBuffer : protected std::streambuf, public std::iostream
63{
64protected:
65 size_t bufsize;
66 char *gbuf, *pbuf;
67
68 StreamBuffer();
69
70 /**
71 * This streambuf method is used for doing unbuffered reads
72 * through the establish tcp socket connection when in interactive mode.
73 * Also this method will handle proper use of buffers if not in
74 * interactive mode.
75 *
76 * @return char from tcp socket connection, EOF if not connected.
77 */
78 int uflow();
79
80 void release(void);
81
82 void allocate(size_t size);
83
84public:
85 /**
86 * Flush the stream input and output buffers, writes pending output.
87 * @return 0 on success, or error code.
88 */
89 int sync(void);
90
91 inline bool is_open(void)
92 {return bufsize > 0;}
93
94 inline operator bool()
95 {return bufsize > 0;}
96
97 inline bool operator!()
98 {return bufsize == 0;}
99};
100
101/**
102 * Streamable tcp connection between client and server. The tcp stream
103 * class can represent a client connection to a server or an instance of
104 * a service generated by a tcp listener. As a stream class, data can
105 * be manipulated using the << and >> operators.
106 *
107 * @author David Sugar <dyfet@gnutelephony.org>
108 */
109class __EXPORT tcpstream : public StreamBuffer
110{
111private:
112 __LOCAL void allocate(unsigned size);
113 __LOCAL void reset(void);
114
115protected:
116 socket_t so;
117 timeout_t timeout;
118
119 virtual ssize_t _read(char *buffer, size_t size);
120
121 virtual ssize_t _write(const char *buffer, size_t size);
122
123 virtual bool _wait(void);
124
125 /**
126 * Release the tcp stream and destroy the underlying socket.
127 */
128 void release(void);
129
130 /**
131 * This streambuf method is used to load the input buffer
132 * through the established tcp socket connection.
133 *
134 * @return char from get buffer, EOF if not connected.
135 */
136 int underflow(void);
137
138 /**
139 * This streambuf method is used to write the output
140 * buffer through the established tcp connection.
141 * @param ch char to push through.
142 * @return char pushed through.
143 */
144 int overflow(int ch);
145
146 inline socket_t getsocket(void) const
147 {return so;}
148
149public:
150 /**
151 * Copy constructor...
152 * @param copy for object.
153 */
154 tcpstream(const tcpstream& copy);
155
156 /**
157 * Create a stream from an existing tcp listener.
158 * @param server to accept connection from.
159 * @param segsize for tcp segments and buffering.
160 * @param timeout for socket i/o operations.
161 */
162 tcpstream(const TCPServer *server, unsigned segsize = 536, timeout_t timeout = 0);
163
164 /**
165 * Create an unconnected tcp stream object that is idle until opened.
166 * @param family of protocol to create.
167 * @param timeout for socket i/o operations.
168 */
169 tcpstream(int family = PF_INET, timeout_t timeout = 0);
170
171 /**
172 * A convenience constructor that creates a connected tcp stream directly
173 * from an address. The socket is constructed to match the type of the
174 * the address family in the socket address that is passed.
175 * @param address of service to connect to.
176 * @param segsize for tcp segments and buffering.
177 * @param timeout for socket i/o operations.
178 */
179 tcpstream(Socket::address& address, unsigned segsize = 536, timeout_t timeout = 0);
180
181 /**
182 * Destroy a tcp stream.
183 */
184 virtual ~tcpstream();
185
186 /**
187 * See if stream connection is active.
188 * @return true if stream is active.
189 */
190 inline operator bool() const
191 {return so != INVALID_SOCKET && bufsize > 0;};
192
193 /**
194 * See if stream is disconnected.
195 * @return true if stream disconnected.
196 */
197 inline bool operator!() const
198 {return so == INVALID_SOCKET || bufsize == 0;};
199
200 /**
201 * Open a stream connection to a tcp service.
202 * @param address of service to access.
203 * @param segment buffering size to use.
204 */
205 void open(Socket::address& address, unsigned segment = 536);
206
207 /**
208 * Open a stream connectoion to a host and service.
209 * @param host to connect to.
210 * @param service to connect to by name or number as string.
211 * @param segment buffering size to use.
212 */
213 void open(const char *host, const char *service, unsigned segment = 536);
214
215 /**
216 * Close an active stream connection. This does not release the
217 * socket but is a disconnect.
218 */
219 void close(void);
220};
221
222/**
223 * Streamable tcp connection between client and server. The tcp stream
224 * class can represent a client connection to a server or an instance of
225 * a service generated by a tcp listener. As a stream class, data can
226 * be manipulated using the << and >> operators.
227 *
228 * @author David Sugar <dyfet@gnutelephony.org>
229 */
230class __EXPORT pipestream : public StreamBuffer
231{
232public:
233 typedef enum {
234 RDONLY,
235 WRONLY,
236 RDWR
237 } access_t;
238
239private:
240 __LOCAL void allocate(size_t size, access_t mode);
241
242protected:
243 fsys_t rd, wr;
244 shell::pid_t pid;
245
246 /**
247 * Release the stream, detach/do not wait for the process.
248 */
249 void release(void);
250
251 /**
252 * This streambuf method is used to load the input buffer
253 * through the established pipe connection.
254 *
255 * @return char from get buffer, EOF if not connected.
256 */
257 int underflow(void);
258
259 /**
260 * This streambuf method is used to write the output
261 * buffer through the established pipe connection.
262 *
263 * @param ch char to push through.
264 * @return char pushed through.
265 */
266 int overflow(int ch);
267
268public:
269 /**
270 * Create an unopened pipe stream.
271 */
272 pipestream();
273
274 /**
275 * Create child process and start pipe.
276 * @param path to execute.
277 * @param access mode of pipe stream.
278 * @param args to pass to command.
279 * @param env to create in child.
280 * @param size of buffer.
281 */
282 pipestream(const char *command, access_t access, char **args, char **env = NULL, size_t size = 512);
283
284 /**
285 * Destroy a pipe stream.
286 */
287 virtual ~pipestream();
288
289 /**
290 * See if stream connection is active.
291 * @return true if stream is active.
292 */
293 inline operator bool() const
294 {return (bufsize > 0);};
295
296 /**
297 * See if stream is disconnected.
298 * @return true if stream disconnected.
299 */
300 inline bool operator!() const
301 {return bufsize == 0;};
302
303 /**
304 * Open a stream connection to a pipe service.
305 * @param path to execute.
306 * @param access mode of stream.
307 * @param args to pass to command.
308 * @param env to create in child process.
309 * @param buffering size to use.
310 */
311 void open(const char *path, access_t access, char **args, char **env = NULL, size_t buffering = 512);
312
313 /**
314 * Close an active stream connection. This waits for the child to
315 * terminate.
316 */
317 int close(void);
318
319 /**
320 * Force terminate child and close.
321 */
322 void terminate(void);
323
324 inline void cancel(void)
325 {terminate();}
326};
327
328/**
329 * Streamable tcp connection between client and server. The tcp stream
330 * class can represent a client connection to a server or an instance of
331 * a service generated by a tcp listener. As a stream class, data can
332 * be manipulated using the << and >> operators.
333 *
334 * @author David Sugar <dyfet@gnutelephony.org>
335 */
336class __EXPORT filestream : public StreamBuffer
337{
338public:
339 typedef enum {
340 RDONLY,
341 WRONLY,
342 RDWR
343 } access_t;
344
345private:
346 __LOCAL void allocate(size_t size, fsys::access_t mode);
347
348protected:
349 fsys_t fd;
350 fsys::access_t ac;
351
352 /**
353 * This streambuf method is used to load the input buffer
354 * through the established pipe connection.
355 *
356 * @return char from get buffer, EOF if not connected.
357 */
358 int underflow(void);
359
360 /**
361 * This streambuf method is used to write the output
362 * buffer through the established pipe connection.
363 *
364 * @param ch char to push through.
365 * @return char pushed through.
366 */
367 int overflow(int ch);
368
369public:
370 /**
371 * Create an unopened pipe stream.
372 */
373 filestream();
374
375 /**
376 * Create duplicate stream.
377 */
378 filestream(const filestream& copy);
379
380 /**
381 * Create and open a file stream.
382 */
383 filestream(const char *path, unsigned mode, fsys::access_t access, size_t bufsize = 512);
384
385 /**
386 * Open file stream.
387 */
388 filestream(const char *path, fsys::access_t access, size_t bufsize = 512);
389
390 /**
391 * Destroy a file stream.
392 */
393 virtual ~filestream();
394
395 /**
396 * See if stream connection is active.
397 * @return true if stream is active.
398 */
399 inline operator bool() const
400 {return (bufsize > 0);};
401
402 /**
403 * See if stream is disconnected.
404 * @return true if stream disconnected.
405 */
406 inline bool operator!() const
407 {return bufsize == 0;};
408
409 /**
410 * Open a stream connection to a tcp service.
411 */
412 void open(const char *filename, fsys::access_t access, size_t buffering = 512);
413
414 /**
415 * Create a stream connection to a tcp service.
416 */
417 void open(const char *filename, unsigned mode, fsys::access_t access, size_t buffering = 512);
418
419 /**
420 * Close an active stream connection.
421 */
422 void close(void);
423
424 /**
425 * Seek position.
426 */
427 void seek(fsys::offset_t offset);
428
429 /**
430 * Get error flag from last i/o operation.
431 * @return last error.
432 */
433 inline int err(void) const
434 {return fd.err();};
435};
436
437/**
438 * At least with gcc, linking of stream operators was broken. This provides
439 * an auxillory class to solve the issue.
440 */
441class __EXPORT _stream_operators
442{
443private:
444 inline _stream_operators() {};
445
446public:
447 static std::ostream& print(std::ostream& out, const PrintProtocol& format);
448
449 static std::istream& input(std::istream& inp, InputProtocol& format);
450
451 static std::ostream& print(std::ostream& out, const string_t& str);
452
453 static std::istream& input(std::istream& inp, string_t& str);
454
455 static std::ostream& print(std::ostream& out, const stringlist_t& list);
456
457 static std::istream& input(std::istream& in, stringlist_t& list);
458
459};
460
461inline std::ostream& operator<< (std::ostream& out, const PrintProtocol& format)
462 {return _stream_operators::print(out, format);}
463
464inline std::istream& operator>> (std::istream& inp, InputProtocol& format)
465 {return _stream_operators::input(inp, format);}
466
467inline std::ostream& operator<< (std::ostream& out, const string_t& str)
468 {return _stream_operators::print(out, str);}
469
470inline std::istream& operator>> (std::istream& inp, string_t& str)
471 {return _stream_operators::input(inp, str);}
472
473inline std::ostream& operator<< (std::ostream& out, const stringlist_t& list)
474 {return _stream_operators::print(out, list);}
475
476inline std::istream& operator>> (std::istream& in, stringlist_t& list)
477 {return _stream_operators::input(in, list);}
478
479END_NAMESPACE
480
481#endif
482#endif