aboutsummaryrefslogtreecommitdiff
path: root/openssl/protocol.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'openssl/protocol.cxx')
-rw-r--r--openssl/protocol.cxx132
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;
+ }
+}