join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
socketstream.hpp
Go to the documentation of this file.
1
25#ifndef __JOIN_SOCKETSTREAM_HPP__
26#define __JOIN_SOCKETSTREAM_HPP__
27
28// libjoin.
29#include <join/socket.hpp>
30
31// C++.
32#include <streambuf>
33#include <utility>
34#include <memory>
35#include <chrono>
36
37namespace join
38{
42 template <class Protocol>
43 class BasicSocketStreambuf : public std::streambuf
44 {
45 public:
46 using Endpoint = typename Protocol::Endpoint;
47 using Socket = typename Protocol::Socket;
48
53 : _buf (std::make_unique <char []> (2 * _bufsize)),
54 _socket (Socket::Mode::NonBlocking)
55 {
56 }
57
63
70
76 : std::streambuf (std::move (other)),
77 _buf (std::move (other._buf)),
78 _timeout (other._timeout),
79 _socket (std::move (other._socket))
80 {
81 }
82
89 {
90 this->close ();
91
92 std::streambuf::operator= (std::move (other));
93 this->_buf = std::move (other._buf);
94 this->_timeout = other._timeout;
95 this->_socket = std::move (other._socket);
96
97 return *this;
98 }
99
104 {
105 if (this->_socket.connected ())
106 {
107 this->overflow (traits_type::eof ());
108 }
109 }
110
117 {
118 if (this->_socket.bind (endpoint) == -1)
119 {
120 return nullptr;
121 }
122
123 return this;
124 }
125
132 {
133 if (this->_socket.connect (endpoint) == -1)
134 {
135 if (lastError != Errc::TemporaryError)
136 {
137 return nullptr;
138 }
139
140 if (!this->_socket.waitConnected (this->_timeout))
141 {
142 this->_socket.close ();
143 return nullptr;
144 }
145 }
146
147 return this;
148 }
149
155 {
156 if (this->_socket.connected () && (this->overflow (traits_type::eof ()) == traits_type::eof ()))
157 {
158 return nullptr;
159 }
160
161 if (this->_socket.disconnect () == -1)
162 {
163 if (lastError != Errc::TemporaryError)
164 {
165 return nullptr;
166 }
167
168 if (!this->_socket.waitDisconnected (this->_timeout))
169 {
170 return nullptr;
171 }
172 }
173
174 return this;
175 }
176
181 void close ()
182 {
183 this->_socket.close ();
184 }
185
190 void timeout (int ms)
191 {
192 this->_timeout = ms;
193 }
194
199 int timeout () const
200 {
201 return this->_timeout;
202 }
203
209 {
210 return this->_socket;
211 }
212
213 protected:
218 virtual int_type underflow () override
219 {
220 if (!this->_socket.connected ())
221 {
223 return traits_type::eof ();
224 }
225
226 if (this->eback () == nullptr)
227 {
228 this->setg (this->_buf.get (), this->_buf.get (), this->_buf.get ());
229 }
230
231 if (this->gptr () == this->egptr ())
232 {
233 for (;;)
234 {
235 int nread = this->_socket.read (this->eback (), _bufsize);
236 if (nread == -1)
237 {
238 if (lastError == Errc::TemporaryError)
239 {
240 if (this->_socket.waitReadyRead (this->_timeout))
241 {
242 continue;
243 }
244 }
245 this->_socket.close();
246 return traits_type::eof ();
247 }
248
249 this->setg (this->eback (), this->eback (), this->eback () + nread);
250 break;
251 }
252 }
253
254 return traits_type::to_int_type (*this->gptr ());
255 }
256
262 virtual int_type overflow (int_type c = traits_type::eof ()) override
263 {
264 if (!this->_socket.connected ())
265 {
267 return traits_type::eof ();
268 }
269
270 if (this->pbase () == nullptr)
271 {
272 this->setp (this->_buf.get () + _bufsize, this->_buf.get () + (2 * _bufsize));
273 }
274
275 if ((this->pptr () == this->epptr ()) || (c == traits_type::eof ()))
276 {
277 std::streamsize pending = this->pptr () - this->pbase ();
278 if (pending)
279 {
280 if (this->_socket.writeExactly (this->pbase (), pending, this->_timeout) == -1)
281 {
282 this->_socket.close ();
283 return traits_type::eof ();
284 }
285 }
286
287 this->setp (this->pbase (), this->pbase () + _bufsize);
288
289 if (c == traits_type::eof ())
290 {
291 return traits_type::not_eof (c);
292 }
293 }
294
295 return this->sputc (traits_type::to_char_type (c));
296 }
297
302 virtual int_type sync () override
303 {
304 if (!this->_socket.connected () || (this->overflow () == traits_type::eof ()))
305 {
306 return -1;
307 }
308 return 0;
309 }
310
312 static const std::streamsize _bufsize = 4096;
313
315 std::unique_ptr <char []> _buf;
316
318 int _timeout = 30000;
319
322 };
323
327 template <class Protocol>
328 class BasicSocketStream : public std::iostream
329 {
330 public:
331 using SocketStreambuf = BasicSocketStreambuf <Protocol>;
332 using Endpoint = typename Protocol::Endpoint;
333 using Socket = typename Protocol::Socket;
334
339 : std::iostream (&_sockbuf)
340 {
341 }
342
347 BasicSocketStream (const BasicSocketStream& other) = delete;
348
355
361 : std::iostream (std::move (other)),
362 _sockbuf (std::move (other._sockbuf))
363 {
364 this->set_rdbuf (&this->_sockbuf);
365 }
366
373 {
374 std::iostream::operator= (std::move (other));
375 this->_sockbuf = std::move (other._sockbuf);
376 return *this;
377 }
378
382 virtual ~BasicSocketStream () = default;
383
389 virtual void bind (const Endpoint& endpoint)
390 {
391 if (this->_sockbuf.bind (endpoint) == nullptr)
392 {
393 this->setstate (std::ios_base::failbit);
394 }
395 }
396
402 virtual void connect (const Endpoint& endpoint)
403 {
404 if (this->_sockbuf.connect (endpoint) == nullptr)
405 {
406 this->setstate (std::ios_base::failbit);
407 }
408 }
409
414 virtual void disconnect ()
415 {
416 if (this->_sockbuf.disconnect () == nullptr)
417 {
418 this->setstate (std::ios_base::failbit);
419 }
420 }
421
426 virtual void close ()
427 {
428 this->_sockbuf.close ();
429 }
430
436 {
437 return this->_sockbuf.socket ().localEndpoint ();
438 }
439
445 {
446 return this->_sockbuf.socket ().remoteEndpoint ();
447 }
448
453 bool opened ()
454 {
455 return this->_sockbuf.socket ().opened ();
456 }
457
462 bool connected ()
463 {
464 return this->_sockbuf.socket ().connected ();
465 }
466
471 bool encrypted ()
472 {
473 return this->_sockbuf.socket ().encrypted ();
474 }
475
480 void timeout (int ms)
481 {
482 this->_sockbuf.timeout (ms);
483 }
484
489 int timeout () const
490 {
491 return this->_sockbuf.timeout ();
492 }
493
499 {
500 return this->_sockbuf.socket ();
501 }
502
503 protected:
506 };
507
511 template <class Protocol>
512 class BasicTlsStream : public BasicSocketStream <Protocol>
513 {
514 public:
515 using SocketStreambuf = BasicSocketStreambuf <Protocol>;
516 using Endpoint = typename Protocol::Endpoint;
517 using Socket = typename Protocol::Socket;
518
523 : BasicSocketStream <Protocol> ()
524 {
525 }
526
531 BasicTlsStream (const BasicTlsStream& other) = delete;
532
538 BasicTlsStream& operator=(const BasicTlsStream& other) = delete;
539
545 : BasicSocketStream <Protocol> (std::move (other))
546 {
547 }
548
555 {
556 BasicSocketStream <Protocol>::operator= (std::move (other));
557
558 return *this;
559 }
560
564 virtual ~BasicTlsStream () = default;
565
571 {
572 if (this->_sockbuf.socket ().startEncryption () == -1)
573 {
574 if (lastError == Errc::TemporaryError)
575 {
576 if (this->_sockbuf.socket ().waitEncrypted (this->timeout ()))
577 return;
578 }
579
580 this->setstate (std::ios_base::failbit);
581 }
582 }
583
589 void connectEncrypted (const Endpoint& endpoint)
590 {
591 if (this->_sockbuf.connect (endpoint) == nullptr)
592 {
593 this->setstate (std::ios_base::failbit);
594 }
595 else
596 {
597 this->startEncryption ();
598 if (this->fail ())
599 {
600 this->close ();
601 }
602 }
603 }
604
611 int setCertificate (const std::string& cert, const std::string& key = "")
612 {
613 return this->_sockbuf.socket ().setCertificate (cert, key);
614 }
615
621 int setCaPath (const std::string& caPath)
622 {
623 return this->_sockbuf.socket ().setCaPath (caPath);
624 }
625
631 int setCaFile (const std::string& caFile)
632 {
633 return this->_sockbuf.socket ().setCaFile (caFile);
634 }
635
641 void setVerify (bool verify, int depth = -1)
642 {
643 return this->_sockbuf.socket ().setVerify (verify, depth);
644 }
645
651 int setCipher (const std::string &cipher)
652 {
653 return this->_sockbuf.socket ().setCipher (cipher);
654 }
655
661 int setCipher_1_3 (const std::string &cipher)
662 {
663 return this->_sockbuf.socket ().setCipher_1_3 (cipher);
664 }
665 };
666}
667
668#endif
socket stream class.
Definition socketstream.hpp:329
typename Protocol::Endpoint Endpoint
Definition socketstream.hpp:332
BasicSocketStream(const BasicSocketStream &other)=delete
copy constructor.
const Endpoint & remoteEndpoint()
determine the remote endpoint associated with this socket.
Definition socketstream.hpp:444
BasicSocketStream()
default constructor.
Definition socketstream.hpp:338
virtual ~BasicSocketStream()=default
destroy the socket stream instance.
BasicSocketStream(BasicSocketStream &&other)
move constructor.
Definition socketstream.hpp:360
Socket & socket()
get the nested socket.
Definition socketstream.hpp:498
typename Protocol::Socket Socket
Definition socketstream.hpp:333
SocketStreambuf _sockbuf
associated stream buffer.
Definition socketstream.hpp:505
BasicSocketStream & operator=(BasicSocketStream &&other)
move assignment operator.
Definition socketstream.hpp:372
bool opened()
check if the socket is opened.
Definition socketstream.hpp:453
Endpoint localEndpoint()
determine the local endpoint associated with this socket.
Definition socketstream.hpp:435
bool connected()
check if the socket is connected.
Definition socketstream.hpp:462
virtual void connect(const Endpoint &endpoint)
make a connection to the given endpoint.
Definition socketstream.hpp:402
virtual void bind(const Endpoint &endpoint)
assigns the specified endpoint to the socket.
Definition socketstream.hpp:389
BasicSocketStream & operator=(const BasicSocketStream &other)=delete
copy assignment operator.
virtual void close()
close the connection.
Definition socketstream.hpp:426
void timeout(int ms)
set the socket timeout.
Definition socketstream.hpp:480
virtual void disconnect()
shutdown the connection.
Definition socketstream.hpp:414
int timeout() const
get the current timeout in milliseconds.
Definition socketstream.hpp:489
bool encrypted()
check if the socket is secure.
Definition socketstream.hpp:471
socket stream buffer class.
Definition socketstream.hpp:44
BasicSocketStreambuf()
default constructor.
Definition socketstream.hpp:52
std::unique_ptr< char[]> _buf
internal buffer.
Definition socketstream.hpp:315
typename Protocol::Endpoint Endpoint
Definition socketstream.hpp:46
BasicSocketStreambuf * connect(const Endpoint &endpoint)
make a connection to the given endpoint.
Definition socketstream.hpp:131
int _timeout
timeout.
Definition socketstream.hpp:318
virtual ~BasicSocketStreambuf()
destroy the socket stream buffer instance.
Definition socketstream.hpp:103
Socket & socket()
get the nested socket.
Definition socketstream.hpp:208
static const std::streamsize _bufsize
internal buffer size.
Definition socketstream.hpp:312
Socket _socket
internal socket.
Definition socketstream.hpp:321
virtual int_type underflow() override
reads characters from the associated input sequence to the get area.
Definition socketstream.hpp:218
BasicSocketStreambuf * disconnect()
shutdown the connection.
Definition socketstream.hpp:154
BasicSocketStreambuf * bind(const Endpoint &endpoint)
assigns the specified endpoint to the socket.
Definition socketstream.hpp:116
void close()
close the connection.
Definition socketstream.hpp:181
BasicSocketStreambuf & operator=(const BasicSocketStreambuf &other)=delete
copy assignment operator.
BasicSocketStreambuf(const BasicSocketStreambuf &other)=delete
copy constructor.
virtual int_type overflow(int_type c=traits_type::eof()) override
writes characters to the associated output sequence from the put area.
Definition socketstream.hpp:262
int timeout() const
get the current timeout in milliseconds.
Definition socketstream.hpp:199
void timeout(int ms)
set the socket timeout.
Definition socketstream.hpp:190
typename Protocol::Socket Socket
Definition socketstream.hpp:47
BasicSocketStreambuf(BasicSocketStreambuf &&other)
move constructor.
Definition socketstream.hpp:75
virtual int_type sync() override
synchronizes the buffers with the associated character sequence.
Definition socketstream.hpp:302
TLS stream class.
Definition socketstream.hpp:513
BasicTlsStream & operator=(BasicTlsStream &&other)
move assignment operator.
Definition socketstream.hpp:554
int setCaPath(const std::string &caPath)
set the location of the trusted CA certificates.
Definition socketstream.hpp:621
void startEncryption()
start socket encryption (perform TLS handshake).
Definition socketstream.hpp:570
BasicTlsStream()
default constructor.
Definition socketstream.hpp:522
int setCipher_1_3(const std::string &cipher)
set the cipher list (TLSv1.3).
Definition socketstream.hpp:661
int setCipher(const std::string &cipher)
set the cipher list (TLSv1.2 and below).
Definition socketstream.hpp:651
BasicTlsStream(BasicTlsStream &&other)
move constructor.
Definition socketstream.hpp:544
typename Protocol::Endpoint Endpoint
Definition socketstream.hpp:516
void connectEncrypted(const Endpoint &endpoint)
make an encrypted connection to the given endpoint.
Definition socketstream.hpp:589
BasicTlsStream(const BasicTlsStream &other)=delete
copy constructor.
BasicTlsStream & operator=(const BasicTlsStream &other)=delete
copy assignment operator.
int setCertificate(const std::string &cert, const std::string &key="")
set the certificate and the private key.
Definition socketstream.hpp:611
void setVerify(bool verify, int depth=-1)
Enable/Disable the verification of the peer certificate.
Definition socketstream.hpp:641
int setCaFile(const std::string &caFile)
set the location of the trusted CA certificate file.
Definition socketstream.hpp:631
typename Protocol::Socket Socket
Definition socketstream.hpp:517
virtual ~BasicTlsStream()=default
destroy the TLS stream instance.
const std::string key(65, 'a')
key.
Definition acceptor.hpp:32
std::error_code make_error_code(join::Errc code)
Create an std::error_code object.
Definition error.cpp:154
Definition error.hpp:106