diff options
Diffstat (limited to 'openssl/protocol.cxx')
-rw-r--r-- | openssl/protocol.cxx | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/openssl/protocol.cxx b/openssl/protocol.cxx new file mode 100644 index 0000000..e74b35e --- /dev/null +++ b/openssl/protocol.cxx @@ -0,0 +1,132 @@ +// file : openssl/protocol.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2018 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include <openssl/protocol.hxx> + +#include <sys/un.h> // sockaddr_un +#include <sys/types.h> +#include <sys/socket.h> + +#include <cstring> // strcpy() + +namespace openssl +{ + using namespace std; + + auto_fd + connect (const path& p) + { + auto_fd sock (socket (AF_UNIX, SOCK_STREAM, 0)); + + if (sock.get () == -1) + throw_system_ios_failure (errno); + + struct sockaddr_un addr; + memset (&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + + if (p.string ().size () >= sizeof (addr.sun_path)) + throw_generic_ios_failure (ENAMETOOLONG); + + strcpy (addr.sun_path, p.string ().c_str ()); + + if (connect (sock.get (), + reinterpret_cast<sockaddr*> (&addr), + sizeof (addr)) == -1) + throw_system_ios_failure (errno); + + return sock; + } + + ostream& + operator<< (ostream& os, const request& r) + { + // Write the header: command, arguments count and input data length. + // + os << r.cmd << ' ' << r.args.size () << ' ' << r.input.size () << '\n'; + + // Write the arguments. + // + for (const string& a: r.args) + os.write (a.c_str (), a.size () + 1); // Includes the trailing '\0'; + + // Write the input data. + // + os.write (r.input.data (), r.input.size ()); + return os << flush; + } + + istream& + operator>> (istream& is, request& r) + { + // Read the header: command, arguments count and input data length. + // + size_t na, ni; + is >> r.cmd >> na >> ni; + + if (is.get () != '\n') + { + is.setstate (istream::failbit); + return is; + } + + // Read the arguments. + // + for (string l; na != 0 && !eof (getline (is, l, '\0')); --na) + r.args.push_back (move (l)); + + if (na != 0) + { + is.setstate (istream::failbit); + return is; + } + + // Read the input data. + // + r.input.resize (ni); + return is.read (r.input.data (), ni); + } + + ostream& + operator<< (ostream& os, const response& r) + { + // Write the header: status and output/error data lengths. + // + os << r.status << ' ' << r.output.size () << ' ' << r.error.size () + << '\n'; + + // Write the output and error data. + // + os.write (r.output.data (), r.output.size ()); + os.write (r.error.data (), r.error.size ()); + return os << flush; + } + + istream& + operator>> (istream& is, response& r) + { + // Read the header: status and output/error data lengths. + // + size_t no, ne; + is >> r.status >> no >> ne; + + if (is.get () != '\n') + { + is.setstate (istream::failbit); + return is; + } + + // Read the output data. + // + r.output.resize (no); + is.read (r.output.data (), no); + + // Read the error (text) data. + // + for (r.error.reserve (ne); ne != 0; --ne) + r.error.push_back (is.get ()); + + return is; + } +} |