// file : openssl/protocol.cxx -*- C++ -*- // license : MIT; see accompanying LICENSE file #include #include // sockaddr_un #include #include #include // 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 (&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; } }