MFEM  v4.3.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
socketstream.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2021, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-806117.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability visit https://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 
12 #ifndef MFEM_SOCKETSTREAM
13 #define MFEM_SOCKETSTREAM
14 
15 #include "../config/config.hpp"
16 #include "error.hpp"
17 #include "globals.hpp"
18 
19 #ifdef MFEM_USE_GNUTLS
20 #include <gnutls/gnutls.h>
21 #if GNUTLS_VERSION_NUMBER < 0x020800
22 #error "MFEM requires GnuTLS version >= 2.8.0"
23 #endif
24 // Use X.509 certificates: (comment out to use OpenPGP keys)
25 #define MFEM_USE_GNUTLS_X509
26 #endif
27 
28 namespace mfem
29 {
30 
31 class socketbuf : public std::streambuf
32 {
33 protected:
35  static const int buflen = 1024;
37 
38 public:
40  {
41  socket_descriptor = -1;
42  }
43 
44  explicit socketbuf(int sd)
45  {
46  socket_descriptor = sd;
47  setp(obuf, obuf + buflen);
48  }
49 
50  socketbuf(const char hostname[], int port)
51  {
52  socket_descriptor = -1;
53  open(hostname, port);
54  }
55 
56  /** @brief Attach a new socket descriptor to the socketbuf. Returns the old
57  socket descriptor which is NOT closed. */
58  virtual int attach(int sd);
59 
60  /// Detach the current socket descriptor from the socketbuf.
61  int detach() { return attach(-1); }
62 
63  /** @brief Open a socket on the 'port' at 'hostname' and store the socket
64  descriptor. Returns 0 if there is no error, otherwise returns -1. */
65  virtual int open(const char hostname[], int port);
66 
67  /// Close the current socket descriptor.
68  virtual int close();
69 
70  /// Returns the attached socket descriptor.
72 
73  /** @brief Returns true if the socket is open and has a valid socket
74  descriptor. Otherwise returns false. */
75  bool is_open() { return (socket_descriptor >= 0); }
76 
77  virtual ~socketbuf() { close(); }
78 
79 protected:
80  virtual int sync();
81 
82  virtual int_type underflow();
83 
84  virtual int_type overflow(int_type c = traits_type::eof());
85 
86  virtual std::streamsize xsgetn(char_type *s__, std::streamsize n__);
87 
88  virtual std::streamsize xsputn(const char_type *s__, std::streamsize n__);
89 };
90 
91 
92 #ifdef MFEM_USE_GNUTLS
93 
95 {
96 protected:
97  int res;
98 
99 public:
100  GnuTLS_status() : res(GNUTLS_E_SUCCESS) { }
101 
102  bool good() const { return (res == GNUTLS_E_SUCCESS); }
103 
104  void set_result(int result) { res = result; }
105 
106  int get_result() const { return res; }
107 
108  void print_on_error(const char *msg) const
109  {
110  if (good()) { return; }
111  mfem::out << "Error in " << msg << ": " << gnutls_strerror(res)
112  << std::endl;
113  }
114 };
115 
117 {
118 protected:
119  gnutls_dh_params_t dh_params;
121 
122  void generate_dh_params();
123 
124 public:
127 
129 
130  void set_log_level(int level)
131  { if (status.good()) { gnutls_global_set_log_level(level); } }
132 
133  gnutls_dh_params_t get_dh_params()
134  {
135  if (!dh_params) { generate_dh_params(); }
136  return dh_params;
137  }
138 };
139 
141 {
142 protected:
143  gnutls_certificate_credentials_t my_cred;
144  unsigned int my_flags;
145 
146 public:
149 
151  const char *pubkey_file,
152  const char *privkey_file,
153  const char *trustedkeys_file,
154  unsigned int flags);
156  {
157  if (my_cred) { gnutls_certificate_free_credentials(my_cred); }
158  }
159 
160  gnutls_certificate_credentials_t get_cred() const { return my_cred; }
161  unsigned int get_flags() const { return my_flags; }
162 };
163 
165 {
166 protected:
168  gnutls_session_t session;
170 
172  gnutls_certificate_credentials_t my_cred; // same as params.my_cred
173 
174  void handshake();
175  void start_session();
176  void end_session();
177 
178 public:
180  : session_started(false), params(p), my_cred(params.get_cred())
182 
183  virtual ~GnuTLS_socketbuf() { close(); }
184 
185  bool gnutls_good() const { return status.good(); }
186 
187  /** Attach a new socket descriptor to the socketbuf. Returns the old socket
188  descriptor which is NOT closed. */
189  virtual int attach(int sd);
190 
191  virtual int open(const char hostname[], int port);
192 
193  virtual int close();
194 
195 protected:
196  virtual int sync();
197 
198  virtual int_type underflow();
199 
200  // Same as in the base class:
201  // virtual int_type overflow(int_type c = traits_type::eof());
202 
203  virtual std::streamsize xsgetn(char_type *s__, std::streamsize n__);
204 
205  virtual std::streamsize xsputn(const char_type *s__, std::streamsize n__);
206 };
207 
208 #endif // MFEM_USE_GNUTLS
209 
210 class socketstream : public std::iostream
211 {
212 protected:
215 
216  void set_socket(bool secure);
217  inline void check_secure_socket();
218 #ifdef MFEM_USE_GNUTLS
219  static int num_glvis_sockets;
223  static void remove_socket();
224  inline void set_secure_socket(const GnuTLS_session_params &p);
225 #endif
226 
227 public:
228 #ifdef MFEM_USE_GNUTLS
229  static const bool secure_default = true;
230 #else
231  static const bool secure_default = false;
232 #endif
233 
234  /** @brief Create a socket stream without connecting to a host.
235 
236  If 'secure' is true, (GnuTLS support must be enabled) then the connection
237  will use GLVis client session keys from ~/.config/glvis/client for GnuTLS
238  identification. If you want to use other GnuTLS session keys or
239  parameters, use the constructor from GnuTLS_session_params. */
240  socketstream(bool secure = secure_default);
241 
242  /** @brief Create a socket stream associated with the given socket buffer.
243  The new object takes ownership of 'buf'. */
244  explicit socketstream(socketbuf *buf)
245  : std::iostream(buf), buf__(buf), glvis_client(false) { }
246 
247  /** @brief Create a socket stream and associate it with the given socket
248  descriptor 's'. The treatment of the 'secure' flag is similar to that in
249  the default constructor. */
250  explicit socketstream(int s, bool secure = secure_default);
251 
252  /** @brief Create a socket stream and connect to the given host and port.
253  The treatment of the 'secure' flag is similar to that in the default
254  constructor. */
255  socketstream(const char hostname[], int port, bool secure = secure_default)
256  : std::iostream(0) { set_socket(secure); open(hostname, port); }
257 
258 #ifdef MFEM_USE_GNUTLS
259  /// Create a secure socket stream using the given GnuTLS_session_params.
260  explicit socketstream(const GnuTLS_session_params &p);
261 #endif
262 
263  socketbuf *rdbuf() { return buf__; }
264 
265  /// Open the socket stream on 'port' at 'hostname'.
266  int open(const char hostname[], int port);
267 
268  /// Close the socketstream.
269  int close() { return buf__->close(); }
270 
271  /// True if the socketstream is open, false otherwise.
272  bool is_open() { return buf__->is_open(); }
273 
274  virtual ~socketstream();
275 };
276 
277 
279 {
280 private:
281  int listen_socket;
282 
283 public:
284  explicit socketserver(int port, int backlog=4);
285 
286  bool good() { return (listen_socket >= 0); }
287 
288  int close();
289 
290  int accept();
291 
292  int accept(socketstream &sockstr);
293 
295 };
296 
297 } // namespace mfem
298 
299 #endif
void set_result(int result)
static GnuTLS_session_params * params
virtual int attach(int sd)
socketstream(socketbuf *buf)
Create a socket stream associated with the given socket buffer. The new object takes ownership of &#39;bu...
virtual int_type underflow()
static int num_glvis_sockets
gnutls_certificate_credentials_t my_cred
bool gnutls_good() const
char ibuf[buflen]
virtual ~socketbuf()
bool is_open()
Returns true if the socket is open and has a valid socket descriptor. Otherwise returns false...
GnuTLS_session_params(GnuTLS_global_state &state, const char *pubkey_file, const char *privkey_file, const char *trustedkeys_file, unsigned int flags)
socketbuf * rdbuf()
int getsocketdescriptor()
Returns the attached socket descriptor.
gnutls_session_t session
gnutls_certificate_credentials_t my_cred
void set_socket(bool secure)
gnutls_dh_params_t get_dh_params()
socketstream(const char hostname[], int port, bool secure=secure_default)
Create a socket stream and connect to the given host and port. The treatment of the &#39;secure&#39; flag is ...
int close()
Close the socketstream.
int get_result() const
gnutls_dh_params_t dh_params
virtual std::streamsize xsgetn(char_type *s__, std::streamsize n__)
bool good() const
virtual std::streamsize xsputn(const char_type *s__, std::streamsize n__)
virtual int close()
Close the current socket descriptor.
virtual int open(const char hostname[], int port)
Open a socket on the &#39;port&#39; at &#39;hostname&#39; and store the socket descriptor. Returns 0 if there is no e...
socketstream(bool secure=secure_default)
Create a socket stream without connecting to a host.
char obuf[buflen]
virtual int_type underflow()
gnutls_certificate_credentials_t get_cred() const
void set_secure_socket(const GnuTLS_session_params &p)
static GnuTLS_session_params & add_socket()
virtual int_type overflow(int_type c=traits_type::eof())
bool is_open()
True if the socketstream is open, false otherwise.
virtual int attach(int sd)
Attach a new socket descriptor to the socketbuf. Returns the old socket descriptor which is NOT close...
GnuTLS_socketbuf(const GnuTLS_session_params &p)
virtual std::streamsize xsgetn(char_type *s__, std::streamsize n__)
void print_on_error(const char *msg) const
GnuTLS_global_state & state
virtual int sync()
virtual int open(const char hostname[], int port)
Open a socket on the &#39;port&#39; at &#39;hostname&#39; and store the socket descriptor. Returns 0 if there is no e...
static const int buflen
socketserver(int port, int backlog=4)
socketbuf(const char hostname[], int port)
int open(const char hostname[], int port)
Open the socket stream on &#39;port&#39; at &#39;hostname&#39;.
static void remove_socket()
virtual int close()
Close the current socket descriptor.
const GnuTLS_session_params & params
unsigned int get_flags() const
static const bool secure_default
RefCoord s[3]
static GnuTLS_global_state * state
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:66
int detach()
Detach the current socket descriptor from the socketbuf.
virtual std::streamsize xsputn(const char_type *s__, std::streamsize n__)
void set_log_level(int level)