summaryrefslogtreecommitdiff
path: root/lib/psocksxx/sockstreambuf.h
blob: ac1ae2f9cf49ecf7a7c0026732f782ebd6a0655c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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
177
178
179
180
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
212
213
214
215
216
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
/*
*  psocksxx - A C++ wrapper for POSIX sockets
*  Copyright (C) 2013 Uditha Atukorala
*
*  This software library is free software; you can redistribute it and/or modify
*  it under the terms of the GNU Lesser General Public License as published by
*  the Free Software Foundation; either version 3 of the License, or
*  (at your option) any later version.
*
*  This software library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public License
*  along with this software library. If not, see <http://www.gnu.org/licenses/>.
*
*/

#ifndef PSOCKSXX_SOCKSTREAMBUF_H
#define PSOCKSXX_SOCKSTREAMBUF_H

#include <psocksxx/socktimeoutexception.h>
#include <psocksxx/sockaddr.h>

#include <streambuf>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

#ifndef SOCKSTREAMBUF_SIZE
#define SOCKSTREAMBUF_SIZE 1024
#endif

#ifndef SOCKSTREAMBUF_PUTBACK_SIZE
#define SOCKSTREAMBUF_PUTBACK_SIZE 8
#endif


namespace psocksxx {

	/**
	*   @brief Socket stream buffer class
	*
	*   This buffer class associates its both input and output
	*   sequences with an external POSIX socket.
	*/
	class sockstreambuf : public std::streambuf {
	public:

		/** socket data type definition */
		typedef int socket_t;

		/** socket end-of-file type */
		enum eof_t {
			eof = -1       /*!< end of file */
		};

		/** socket domains type definition */
		enum socket_domain_t {
			pf_local   = PF_LOCAL,        /*!< Host-internal protocols */
			pf_inet    = PF_INET,         /*!< Internet version 4 protocols */
			pf_route   = PF_ROUTE,        /*!< Internal Routing protocol */
			pf_key     = PF_KEY,          /*!< Internal key-management function */
			pf_inet6   = PF_INET6         /*!< Internet version 6 protocols */
		};

		/** socket types type definition */
		enum socket_type_t {
			sock_stream     = SOCK_STREAM,
			sock_dgram      = SOCK_DGRAM,
			sock_raw        = SOCK_RAW,
			sock_rdm        = SOCK_RDM,
			sock_seqpacket  = SOCK_SEQPACKET
		};

		/** socket protocols type definition */
		enum socket_protocol_t {
			proto_unspec    = 0,               /*!< Unspecified system default */
			ipproto_ip      = IPPROTO_IP,      /*!< Internet protocol */
			ipproto_ipv6    = IPPROTO_IPV6,    /*!< Internet Protocol Version 6 */
			ipproto_icmp    = IPPROTO_ICMP,    /*!< Control message protocol */
			ipproto_raw     = IPPROTO_RAW,     /*!< Raw IP Packets Protocol */
			ipproto_tcp     = IPPROTO_TCP,     /*!< Transmission control protocol */
			ipproto_udp     = IPPROTO_UDP      /*!< User datagram protocol */
		};


		sockstreambuf() throw();          //!< constructor
		virtual ~sockstreambuf();         //!< destructor

		/**
		*   @brief overloaded constructor
		*   @param socket socket data
		*
		*   Create an instance with the passed in sockstreambuf::socket_t
		*   type socket. It is assumed that the socket is initialised and
		*   ready to use.
		*
		*/
		sockstreambuf( socket_t socket ) throw();

		/**
		*   @brief get internal socket data
		*   @return socket data
		*
		*   Returns a read-only reference to the internal POSIX socket
		*   data.
		*
		*/
		const socket_t & socket() const throw();

		/**
		*   @brief open a socket
		*   @param domain communications domain for the socket
		*   @param type socket communications type
		*   @param proto socket communications protocol
		*   @throw psocksxx::sockexception socket exception
		*
		*   Open a socket and initialise socket communications.
		*
		*/
		void open( socket_domain_t domain, socket_type_t type, socket_protocol_t proto = proto_unspec ) throw( sockexception );

		/**
		*   @brief close open sockets
		*
		*   Close any open socket connections used by this buffer. This
		*   will also flush any data in the buffer before closing.
		*
		*/
		void close() throw();

		/**
		*   @brief flush the socket output buffer
		*   @return number of characters flushed
		*   @throw psocksxx::socktimeoutexception on socket timeout
		*
		*   Flush the socket buffer by writing date into the
		*   socket and returns the number of characters flushed.
		*   If the output buffer is empty sockstreambuf::eof is returned.
		*
		*/
		virtual int flush() throw( socktimeoutexception );


		/**
		*   @brief initiate a connection on a socket
		*   @param dest_addr destination address to connect to
		*   @param timeout connection timeout value in seconds
		*   @throw psocksxx::sockexception socket exception
		*   @throw psocksxx::socktimeoutexception connection timeout
		*          exception
		*
		*   Initiate a connection on a socket previously opened using
		*   open() method. If the timeout value is 0 (default) then
		*   the timeouts are ignored.
		*
		*/
		void connect( const sockaddr * dest_addr, unsigned int timeout = 0 ) throw( sockexception, socktimeoutexception );

		/**
		*   @brief initiate a connection on a socket
		*   @param dest_addr destination address to connect to
		*   @param timeout connection timeout value as a reference to a
		*          @c timeval structure
		*
		*   @throw psocksxx::sockexception socket exception
		*   @throw psocksxx::socktimeoutexception connection timeout
		*          exception
		*
		*   Initiate a connection on a socket previously opened using
		*   open() method.
		*
		*/
		void connect( const sockaddr * dest_addr, timeval * timeout ) throw( sockexception, socktimeoutexception );

		/**
		*   @brief bind the socket to a specified address
		*   @param bind_addr address to bind to
		*   @param reuse_addr allow address to be re-used
		*   @throw psocksxx::sockexception socket exception
		*
		*   After a socket is configured using open() this method can
		*   be used to assign an address to it. If @c reuse_addr is set
		*   to @c true then this will try to re-use the address unless
		*   the address is actively listening.
		*
		*/
		void bind( const sockaddr * bind_addr, bool reuse_addr = false ) throw( sockexception );

		/**
		*   @brief make the socket passive and capable of accepting connections
		*   @param backlog maximum length of the queue for pending connections
		*                  and defaults to SOMAXCONN (128) defined in @c <sys/socket.h>
		*
		*   @throw psocksxx::sockexception socket exception
		*
		*   This method will make the currently opened socket connection
		*   to passive and capable of accepting client connections using accept()
		*   method.
		*
		*/
		void listen( int backlog = SOMAXCONN ) throw( sockexception );

		/**
		*   @brief accept a connection on a listening (passive) socket
		*   @throw psocksxx::sockexception socket exception
		*   @return peer socket data structure
		*
		*   This method will accept incoming connections on a socket
		*   set to be passive using the listen() method. Upon success
		*   this will return the peer socket data structure that can be used
		*   to create a socket stream buffer instance to communicate
		*   with the accepted socket connection.
		*
		*/
		socket_t accept() throw( sockexception );

		/**
		*   @brief set the timeout value for the socket
		*   @param sec seconds
		*   @param usec microseconds
		*   @return a reference to the internal timeout structure
		*
		*   This method will set the timeout for the socket and make this
		*   a non-blocking socket. Note that you cannot clear the timeout
		*   by passing in a 0 timeout, use clear_timeout() method instead.
		*
		*/
		const timeval * timeout( time_t sec, suseconds_t usec ) throw();

		/**
		*   @brief clear the timeout value for the socket
		*   @return a reference to the internal timeout structure which will
		*           always be a null-pointer (@c 0) after clearing the timeout
		*
		*   This will clear any timeout values set for the socket affectively
		*   making this a blocking socket by default.
		*
		*/
		void * clear_timeout() throw();

		/**
		*   @brief get the timed-out status
		*   @return boolean @c true if timed-out flag is set or @c false
		*           otherwise.
		*
		*   Returns the timed-out status.
		*
		*/
		bool timedout() const throw();


	protected:

		/**
		*   @brief initialise internal buffers
		*/
		void init_buffers() throw();

		/**
		*   @brief cleanup internal buffers
		*/
		void cleanup_buffers() throw();

		/**
		*   @brief sync data with the socket
		*   @return 0 or -1 to denote success or failure
		*
		*   Synchronise the buffer with the associated socket
		*   by flushing data from the buffer to the socket.
		*
		*/
		virtual int sync() throw();

		/**
		*   @brief consumes the buffer by writing the contents to
		*          the socket
		*
		*   @param c additional character to consume
		*   @return sockstreambuf::eof to indicate failure or @a c
		*           if successful.
		*
		*   @throw psocksxx::socktimeoutexception on socket timeout
		*
		*
		*   Consumes the buffer contents and writes to the opened socket.
		*   If @a c is not sockstreambuf::eof then @a c is also written
		*   out.
		*
		*/
		virtual int overflow( int c = eof ) throw( socktimeoutexception );

		/**
		*   @brief read more data into the buffer from the socket
		*   @return the first character from the buffer or sockstreambuf::eof
		*           if no data is available to read
		*
		*   @throw psocksxx::socktimeoutexception on socket timeout
		*
		*
		*   This reads more data into the buffer from the socket when
		*   the input buffer is empty and returns the next readable
		*   character from the buffer. If the buffer is empty and no
		*   data is available through the socket, this returns sockstreambuf::eof.
		*
		*/
		virtual int underflow() throw( socktimeoutexception );

		/**
		*   @brief check for the read/write availability on the socket
		*   @param timeout timeout value reference to a @c timeval structure
		*   @param chk_read check for read availability
		*   @param chk_write check for write availability
		*   @throw psocksxx::sockexception socket exception
		*   @return boolean @c true to denote availability or @c false
		*           if none of the checked actions are available.
		*
		*   This will check the socket for read and/or write availability.
		*
		*/
		bool ready( timeval * timeout, bool chk_read = true, bool chk_write = true ) throw( sockexception );


	private:

		/** POSIX socket data */
		socket_t _socket;

		size_t _bufsize;
		size_t _putbacksize;

		timeval * _timeout;
		bool      _timed_out;


		void init_defaults() throw();

	};

} /* end of namespace psocksxx */

#endif /* !PSOCKSXX_SOCKSTREAMBUF_H */