14#define _CRT_SECURE_NO_WARNINGS
25#include <sys/socket.h>
27#define closesocket (::close)
34#pragma comment(lib, "ws2_32.lib")
40#ifndef MFEM_USE_GNUTLS_X509
41#include <gnutls/openpgp.h>
58 int err_flag = WSAStartup(MAKEWORD(2,2), &wsaData);
61 mfem::out <<
"Error occurred during initialization of WinSock."
70 ~WinsockWrapper() { WSACleanup(); }
73 WinsockWrapper(
const WinsockWrapper&) =
delete;
74 WinsockWrapper& operator=(
const WinsockWrapper&) =
delete;
76 bool Initialized() {
return initialized; }
78 bool initialized =
false;
82static WinsockWrapper wsInit_;
89 setg(NULL, NULL, NULL);
96 struct addrinfo hints, *res, *rp;
98 if (!wsInit_.Initialized())
100 mfem_error(
"Attempting to open socket, but Winsock not initialized.");
104 setg(NULL, NULL, NULL);
107 hints.ai_family = AF_UNSPEC;
108 hints.ai_socktype = SOCK_STREAM;
110 hints.ai_protocol = 0;
112 std::string portStr = std::to_string(port);
113 int s = getaddrinfo(hostname, portStr.c_str(), &hints, &res);
120 for (rp = res; rp != NULL; rp = rp->ai_next)
133 &on,
sizeof(on)) < 0)
168 ssize_t bw, n = pptr() - pbase();
180 mfem::out <<
"Error in send(): " << strerror(errno) << std::endl;
203 mfem::out <<
"Error in recv(): " << strerror(errno) << std::endl;
206 setg(NULL, NULL, NULL);
207 return traits_type::eof();
210 return traits_type::to_int_type(*
ibuf);
217 return traits_type::eof();
219 if (traits_type::eq_int_type(c, traits_type::eof()))
221 return traits_type::not_eof(c);
223 *pptr() = traits_type::to_char_type(c);
232 const std::streamsize bn = egptr() - gptr();
235 traits_type::copy(s__, gptr(), n__);
239 traits_type::copy(s__, gptr(), bn);
240 setg(NULL, NULL, NULL);
241 std::streamsize remain = n__ - bn;
242 char_type *end = s__ + n__;
252 mfem::out <<
"Error in recv(): " << strerror(errno) << std::endl;
255 return (n__ - remain);
266 if (pptr() + n__ <= epptr())
268 traits_type::copy(pptr(), s__, n__);
277 std::streamsize remain = n__;
278 const char_type *end = s__ + n__;
289 mfem::out <<
"Error in send(): " << strerror(errno) << std::endl;
291 return (n__ - remain);
297 traits_type::copy(pptr(), end - remain, remain);
306 listen_socket = socket(PF_INET, SOCK_STREAM, 0);
307 if (listen_socket < 0)
312 if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR,
313 (
char *)(&on),
sizeof(on)) < 0)
315 closesocket(listen_socket);
319 struct sockaddr_in sa;
320 memset(&sa, 0,
sizeof(sa));
321 sa.sin_family = AF_INET;
322 sa.sin_port = htons(port);
323 sa.sin_addr.s_addr = INADDR_ANY;
324 if (bind(listen_socket, (
const struct sockaddr *)&sa,
sizeof(sa)))
326 closesocket(listen_socket);
331 if (listen(listen_socket, backlog) < 0)
333 closesocket(listen_socket);
345 int err_flag = closesocket(listen_socket);
352 return good() ?
::accept(listen_socket, NULL, NULL) : -1;
361 int socketd =
::accept(listen_socket, NULL, NULL);
371#ifdef MFEM_USE_GNUTLS
373static void mfem_gnutls_log_func(
int level,
const char *str)
375 mfem::out <<
"GnuTLS <" << level <<
"> " << str << std::flush;
386 gnutls_global_set_log_function(mfem_gnutls_log_func);
407#if GNUTLS_VERSION_NUMBER >= 0x021200
409 gnutls_sec_param_to_pk_bits(
410 GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LEGACY);
412 unsigned bits = 1024;
414 mfem::out <<
"Generating DH params (" << bits <<
" bits) ..."
428static int mfem_gnutls_verify_callback(gnutls_session_t session)
431#if GNUTLS_VERSION_NUMBER >= 0x030104
432 const char *hostname = (
const char *) gnutls_session_get_ptr(session);
433 int ret = gnutls_certificate_verify_peers3(session, hostname, &status);
436 mfem::out <<
"Error in gnutls_certificate_verify_peers3:"
437 << gnutls_strerror(ret) << std::endl;
438 return GNUTLS_E_CERTIFICATE_ERROR;
442 gnutls_datum_t status_str;
443 gnutls_certificate_type_t type = gnutls_certificate_type_get(session);
444 ret = gnutls_certificate_verification_status_print(
445 status, type, &status_str, 0);
448 mfem::out <<
"Error in gnutls_certificate_verification_status_print:"
449 << gnutls_strerror(ret) << std::endl;
450 return GNUTLS_E_CERTIFICATE_ERROR;
452 mfem::out << status_str.data << std::endl;
453 gnutls_free(status_str.data);
456 int ret = gnutls_certificate_verify_peers2(session, &status);
459 mfem::out <<
"Error in gnutls_certificate_verify_peers2:"
460 << gnutls_strerror(ret) << std::endl;
461 return GNUTLS_E_CERTIFICATE_ERROR;
465 "The certificate is NOT trusted." :
466 "The certificate is trusted.") << std::endl;
470 return status ? GNUTLS_E_CERTIFICATE_ERROR : 0;
475 const char *privkey_file,
const char *trustedkeys_file,
unsigned int flags)
485 gnutls_certificate_allocate_credentials(&
my_cred));
491#ifndef MFEM_USE_GNUTLS_X509
493 gnutls_certificate_set_openpgp_key_file(
494 my_cred, pubkey_file, privkey_file, GNUTLS_OPENPGP_FMT_RAW));
498 gnutls_certificate_set_x509_key_file(
499 my_cred, pubkey_file, privkey_file, GNUTLS_X509_FMT_PEM));
517#ifndef MFEM_USE_GNUTLS_X509
519 gnutls_certificate_set_openpgp_keyring_file(
520 my_cred, trustedkeys_file, GNUTLS_OPENPGP_FMT_RAW));
524 gnutls_certificate_set_x509_trust_file(
525 my_cred, trustedkeys_file, GNUTLS_X509_FMT_PEM);
527#ifdef MFEM_USE_GNUTLS_DEBUG
528 mfem::out <<
"[GnuTLS_session_params::GnuTLS_session_params] "
529 "number of trusted certificates = " << num_certs << std::endl;
532 GNUTLS_E_SUCCESS : GNUTLS_E_CERTIFICATE_ERROR);
537#if GNUTLS_VERSION_NUMBER >= 0x021000
540 gnutls_certificate_set_verify_function(
541 my_cred, mfem_gnutls_verify_callback);
551 gnutls_certificate_set_dh_params(
my_cred, dh_params);
558#ifdef MFEM_USE_GNUTLS_DEBUG
559 mfem::out <<
"[GnuTLS_socketbuf::handshake]" << std::endl;
566 err_flag = gnutls_handshake(
session);
571 mfem::out <<
"handshake successful, TLS version is "
572 << gnutls_protocol_get_name(
573 gnutls_protocol_get_version(
session)) << std::endl;
578 while (err_flag == GNUTLS_E_INTERRUPTED || err_flag == GNUTLS_E_AGAIN);
584#if (defined(MSG_NOSIGNAL) && !defined(_WIN32) && !defined(__APPLE__))
585#define MFEM_USE_GNUTLS_PUSH_FUNCTION
587static ssize_t mfem_gnutls_push_function(
588 gnutls_transport_ptr_t fd_ptr,
const void *data,
size_t datasize)
590 return send((
int)(
long)fd_ptr, data, datasize, MSG_NOSIGNAL);
596#ifdef MFEM_USE_GNUTLS_DEBUG
597 mfem::out <<
"[GnuTLS_socketbuf::start_session]" << std::endl;
606#if GNUTLS_VERSION_NUMBER >= 0x030102
618 const char *priorities;
620 if (gnutls_check_version(
"2.12.0") != NULL)
623#ifndef MFEM_USE_GNUTLS_X509
624 priorities =
"NONE:+VERS-TLS1.2:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:"
625 "+COMP-ALL:+KX-ALL:+CTYPE-OPENPGP:+CURVE-ALL";
627 priorities =
"NONE:+VERS-TLS1.2:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:"
628 "+COMP-ALL:+KX-ALL:+CTYPE-X509:+CURVE-ALL";
634#ifndef MFEM_USE_GNUTLS_X509
635 priorities =
"NORMAL:-CTYPE-X.509";
637 priorities =
"NORMAL:";
642 gnutls_priority_set_direct(
session, priorities, &err_ptr));
646 mfem::out <<
"Error ptr = \"" << err_ptr <<
'"' << std::endl;
654 gnutls_credentials_set(
661 const char *hostname = NULL;
662 gnutls_session_set_ptr(
session, (
void*)hostname);
666 gnutls_certificate_server_set_request(
session, GNUTLS_CERT_REQUIRE);
668#if GNUTLS_VERSION_NUMBER >= 0x030100
669 gnutls_handshake_set_timeout(
670 session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
676#if GNUTLS_VERSION_NUMBER >= 0x030109
679 gnutls_transport_set_ptr(
session,
686#if GNUTLS_VERSION_NUMBER < 0x021000
697 err_flag = gnutls_bye(
session, GNUTLS_SHUT_WR);
699 while (err_flag == GNUTLS_E_AGAIN || err_flag == GNUTLS_E_INTERRUPTED);
704#ifdef MFEM_USE_GNUTLS_PUSH_FUNCTION
707 gnutls_transport_set_push_function(
session, mfem_gnutls_push_function);
721#ifdef MFEM_USE_GNUTLS_DEBUG
722 mfem::out <<
"[GnuTLS_socketbuf::end_session]" << std::endl;
731#ifdef MFEM_USE_GNUTLS_DEBUG
732 mfem::out <<
"[GnuTLS_socketbuf::end_session: gnutls_bye]" << std::endl;
742 while (err_flag == GNUTLS_E_AGAIN || err_flag == GNUTLS_E_INTERRUPTED);
752#ifdef MFEM_USE_GNUTLS_DEBUG
753 mfem::out <<
"[GnuTLS_socketbuf::attach]" << std::endl;
767#ifdef MFEM_USE_GNUTLS_DEBUG
768 mfem::out <<
"[GnuTLS_socketbuf::open]" << std::endl;
772 if (err_flag) {
return err_flag; }
781#ifdef MFEM_USE_GNUTLS_DEBUG
782 mfem::out <<
"[GnuTLS_socketbuf::close]" << std::endl;
794 ssize_t bw, n = pptr() - pbase();
795#ifdef MFEM_USE_GNUTLS_DEBUG
796 mfem::out <<
"[GnuTLS_socketbuf::sync n=" << n <<
']' << std::endl;
801 bw = gnutls_record_send(
session, pptr() - n, n);
802 if (bw == GNUTLS_E_INTERRUPTED || bw == GNUTLS_E_AGAIN) {
continue; }
821#ifdef MFEM_USE_GNUTLS_DEBUG
822 mfem::out <<
"[GnuTLS_socketbuf::underflow ...]" << std::endl;
830 if (br == GNUTLS_E_REHANDSHAKE)
835 while (br == GNUTLS_E_INTERRUPTED || br == GNUTLS_E_AGAIN);
836#ifdef MFEM_USE_GNUTLS_DEBUG
837 mfem::out <<
"[GnuTLS_socketbuf::underflow br=" << br <<
']' << std::endl;
849 setg(NULL, NULL, NULL);
850 return traits_type::eof();
853 return traits_type::to_int_type(*
ibuf);
858#ifdef MFEM_USE_GNUTLS_DEBUG
859 mfem::out <<
"[GnuTLS_socketbuf::xsgetn n__=" << n__ <<
']' << std::endl;
863 const std::streamsize bn = egptr() - gptr();
866 traits_type::copy(s__, gptr(), n__);
870 traits_type::copy(s__, gptr(), bn);
871 setg(NULL, NULL, NULL);
872 std::streamsize remain = n__ - bn;
873 char_type *end = s__ + n__;
879 br = gnutls_record_recv(
session, end - remain, remain);
880 if (br == GNUTLS_E_REHANDSHAKE)
885 while (br == GNUTLS_E_INTERRUPTED || br == GNUTLS_E_AGAIN);
895 return (n__ - remain);
905#ifdef MFEM_USE_GNUTLS_DEBUG
906 mfem::out <<
"[GnuTLS_socketbuf::xsputn n__=" << n__ <<
']' << std::endl;
910 if (pptr() + n__ <= epptr())
912 traits_type::copy(pptr(), s__, n__);
921 std::streamsize remain = n__;
922 const char_type *end = s__ + n__;
925 bw = gnutls_record_send(
session, end - remain, remain);
926 if (bw == GNUTLS_E_INTERRUPTED || bw == GNUTLS_E_AGAIN) {
continue; }
927#ifdef MFEM_USE_GNUTLS_DEBUG
928 mfem::out <<
"[GnuTLS_socketbuf::xsputn bw=" << bw <<
']' << std::endl;
936 return (n__ - remain);
942 traits_type::copy(pptr(), end - remain, remain);
960 std::string home_dir(getenv(
"HOME"));
961 std::string client_dir = home_dir +
"/.config/glvis/client/";
962#ifndef MFEM_USE_GNUTLS_X509
963 std::string pubkey = client_dir +
"pubring.gpg";
964 std::string privkey = client_dir +
"secring.gpg";
965 std::string trustedkeys = client_dir +
"trusted-servers.gpg";
967 std::string pubkey = client_dir +
"cert.pem";
968 std::string privkey = client_dir +
"key.pem";
969 std::string trustedkeys = client_dir +
"trusted-servers.pem";
972 *
state, pubkey.c_str(), privkey.c_str(), trustedkeys.c_str(),
976 mfem::out <<
" public key = " << pubkey <<
'\n'
977 <<
" private key = " << privkey <<
'\n'
978 <<
" trusted keys = " << trustedkeys << std::endl;
979 mfem::out <<
"Error setting GLVis client parameters.\n"
980 "Use the following GLVis script to create your GLVis keys:\n"
981 " bash glvis-keygen.sh [\"Your Name\"] [\"Your Email\"]"
1006 std::iostream::rdbuf(
buf__);
1010 : std::iostream(0), glvis_client(false)
1023#ifdef MFEM_USE_GNUTLS
1026 mfem_error(
"The secure option in class mfem::socketstream can only\n"
1027 "be used when GnuTLS support is enabled.");
1033 std::iostream::rdbuf(
buf__);
1039#ifdef MFEM_USE_GNUTLS
1041 else { setstate(std::ios::failbit); }
1060 int err_flag =
buf__->
open(hostname, port);
1063 setstate(std::ios::failbit);
1075#ifdef MFEM_USE_GNUTLS
void generate_dh_params()
gnutls_dh_params_t get_dh_params()
gnutls_dh_params_t dh_params
unsigned int get_flags() const
GnuTLS_global_state & state
GnuTLS_session_params(GnuTLS_global_state &state, const char *pubkey_file, const char *privkey_file, const char *trustedkeys_file, unsigned int flags)
gnutls_certificate_credentials_t my_cred
virtual int close()
Close the current socket descriptor.
virtual std::streamsize xsgetn(char_type *s__, std::streamsize n__)
virtual int attach(int sd)
gnutls_certificate_credentials_t my_cred
virtual int_type underflow()
virtual std::streamsize xsputn(const char_type *s__, std::streamsize n__)
virtual int open(const char hostname[], int port)
Open a socket on the 'port' at 'hostname' and store the socket descriptor. Returns 0 if there is no e...
const GnuTLS_session_params & params
void set_result(int result)
void print_on_error(const char *msg) const
virtual int attach(int sd)
Attach a new socket descriptor to the socketbuf. Returns the old socket descriptor which is NOT close...
virtual int_type overflow(int_type c=traits_type::eof())
virtual std::streamsize xsputn(const char_type *s__, std::streamsize n__)
virtual int close()
Close the current socket descriptor.
virtual int_type underflow()
virtual std::streamsize xsgetn(char_type *s__, std::streamsize n__)
bool is_open()
Returns true if the socket is open and has a valid socket descriptor. Otherwise returns false.
int getsocketdescriptor()
Returns the attached socket descriptor.
virtual int open(const char hostname[], int port)
Open a socket on the 'port' at 'hostname' and store the socket descriptor. Returns 0 if there is no e...
socketserver(int port, int backlog=4)
void set_secure_socket(const GnuTLS_session_params &p)
void set_socket(bool secure)
static GnuTLS_session_params * params
socketstream(bool secure=secure_default)
Create a socket stream without connecting to a host.
static int num_glvis_sockets
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
static GnuTLS_session_params & add_socket()
static GnuTLS_global_state * state
static void remove_socket()
void check_secure_socket()
void mfem_error(const char *msg)
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
real_t p(const Vector &x, real_t t)