# # # patch "automate_ostream.hh" # from [d80b57babe3d47106cd87acaedf5284e02d6fd1d] # to [abdfca2e10a965e396d448a8777650cb6fcb355e] # # patch "automate_ostream_demuxed.hh" # from [a5919d5b8e031dc9c4b9e47014269af60e38e1e4] # to [d5e068c3a9dadfabf27db883b6a2bb2379eea34e] # # patch "cmd.hh" # from [2704dcd756496bee54d047303d73fe86e4a1434d] # to [5998c5301309d79ea9417b5131af27d9808a2138] # # patch "cmd_automate.cc" # from [5d8b2a02978564165eb1c639b4f75cd052f9f36f] # to [cfd1a9f1dd06fe21e282009a5a53edf39a353355] # # patch "netcmd.cc" # from [49728d5636bd31ff48a2c5138e564c2b1433ffeb] # to [85246fc3470bf61ca4d7f16b3a204dfb65eb1ca1] # # patch "netcmd.hh" # from [5a7cc7bb58fc69f67982c9daa592d6dc29d06b70] # to [f6c60950810184737024220f58f806db5ec1ee2a] # # patch "network/automate_session.cc" # from [aa63e7329bf1e9ba3b3491e5ec07369f71c7941a] # to [eeb9c7d6c3b128d173544ea8210bb6efadb1a3cf] # ============================================================ --- automate_ostream.hh d80b57babe3d47106cd87acaedf5284e02d6fd1d +++ automate_ostream.hh abdfca2e10a965e396d448a8777650cb6fcb355e @@ -12,6 +12,7 @@ #define __AUTOMATE_OSTREAM_HH__ #include +#include #include "lexical_cast.hh" using boost::lexical_cast; @@ -86,6 +87,17 @@ public: out->flush(); } + void write_headers(std::vector > const & headers) + { + for (std::vector >::const_iterator h = headers.begin(); + h != headers.end(); ++h) + { + (*out) << h->first << ": " << h->second << '\n'; + } + (*out) << '\n'; + out->flush(); + } + int_type overflow(int_type c = traits_type::eof()) { @@ -123,6 +135,9 @@ public: virtual void write_out_of_band(char type, std::string const & data) { _M_autobuf.write_out_of_band(type, data); } + + virtual void write_headers(std::vector > const & headers) + { _M_autobuf.write_headers(headers); } }; typedef basic_automate_streambuf automate_streambuf; ============================================================ --- automate_ostream_demuxed.hh a5919d5b8e031dc9c4b9e47014269af60e38e1e4 +++ automate_ostream_demuxed.hh d5e068c3a9dadfabf27db883b6a2bb2379eea34e @@ -71,6 +71,16 @@ public: (*errout) << out << std::endl; } + void write_headers(std::vector > const & headers) + { + i18n_format prefix = F("%s: remote header: ") % prog_name; + for (std::vector >::const_iterator h = headers.begin(); + h != headers.end(); ++h) + { + (*errout) << prefix.str() << h->first << ": " << h->second << std::endl; + } + } + int_type overflow(int_type c = traits_type::eof()) { sync(); @@ -127,6 +137,9 @@ public: virtual void write_out_of_band(char type, std::string const & data) { _M_autobuf.write_out_of_band(type, data); } + + virtual void write_headers(std::vector > const & headers) + { _M_autobuf.write_headers(headers); } }; typedef basic_automate_streambuf_demuxed automate_streambuf_demuxed; ============================================================ --- cmd.hh 2704dcd756496bee54d047303d73fe86e4a1434d +++ cmd.hh 5998c5301309d79ea9417b5131af27d9808a2138 @@ -136,6 +136,8 @@ namespace commands bool can_run_from_stdio() const; }; + + void get_stdio_headers(std::vector > & headers); } inline std::vector ============================================================ --- cmd_automate.cc 5d8b2a02978564165eb1c639b4f75cd052f9f36f +++ cmd_automate.cc cfd1a9f1dd06fe21e282009a5a53edf39a353355 @@ -105,6 +105,12 @@ CMD_AUTOMATE(interface_version, "", output << interface_version << '\n'; } +// these headers are outputted before any other output for stdio and remote_stdio +void commands::get_stdio_headers(std::vector > & headers) +{ + headers.push_back(make_pair("interface-version", interface_version)); +} + // Name: bandtest // Arguments: { info | warning | error | fatal | ticker } // Added in: FIXME @@ -209,6 +215,11 @@ CMD_AUTOMATE_NO_STDIO(stdio, "", automate_ostream os(output, app.opts.automate_stdio_size); automate_reader ar(std::cin); + + std::vector > headers; + commands::get_stdio_headers(headers); + os.write_headers(headers); + vector > params; vector cmdline; global_sanity.set_out_of_band_handler(&out_of_band_to_automate_streambuf, &os); ============================================================ --- netcmd.cc 49728d5636bd31ff48a2c5138e564c2b1433ffeb +++ netcmd.cc 85246fc3470bf61ca4d7f16b3a204dfb65eb1ca1 @@ -113,6 +113,8 @@ netcmd::read(u8 min_version, u8 max_vers case static_cast(data_cmd): case static_cast(delta_cmd): case static_cast(automate_cmd): + case static_cast(automate_headers_request_cmd): + case static_cast(automate_headers_reply_cmd): case static_cast(automate_command_cmd): case static_cast(automate_packet_cmd): case static_cast(usher_cmd): @@ -610,8 +612,55 @@ void } void +netcmd::read_automate_headers_request_cmd() const +{ + size_t pos = 0; + assert_end_of_buffer(payload, pos, "read automate headers request netcmd payload"); +} + +void +netcmd::write_automate_headers_request_cmd() +{ + cmd_code = automate_headers_request_cmd; +} + +void +netcmd::read_automate_headers_reply_cmd(vector > & headers) const +{ + size_t pos = 0; + size_t nheaders = extract_datum_uleb128(payload, pos, + "automate headers reply netcmd, count"); + headers.clear(); + for (size_t i = 0; i < nheaders; ++i) + { + string name; + extract_variable_length_string(payload, name, pos, + "automate headers reply netcmd, name"); + string value; + extract_variable_length_string(payload, value, pos, + "automate headers reply netcmd, value"); + headers.push_back(make_pair(name, value)); + } + assert_end_of_buffer(payload, pos, "automate headers reply netcmd payload"); +} + +void +netcmd::write_automate_headers_reply_cmd(vector > const & headers) +{ + cmd_code = automate_headers_reply_cmd; + + insert_datum_uleb128(headers.size(), payload); + for (vector >::const_iterator h = headers.begin(); + h != headers.end(); ++h) + { + insert_variable_length_string(h->first, payload); + insert_variable_length_string(h->second, payload); + } +} + +void netcmd::read_automate_command_cmd(vector & args, - vector > & opts) const + vector > & opts) const { size_t pos = 0; { @@ -637,7 +686,7 @@ netcmd::read_automate_command_cmd(vector "automate_command netcmd, option name"); string value; extract_variable_length_string(payload, value, pos, - "automate_command netcmd, option name"); + "automate_command netcmd, option value"); opts.push_back(make_pair(name, value)); } } ============================================================ --- netcmd.hh 5a7cc7bb58fc69f67982c9daa592d6dc29d06b70 +++ netcmd.hh f6c60950810184737024220f58f806db5ec1ee2a @@ -92,8 +92,10 @@ typedef enum // automation commands automate_cmd = 10, - automate_command_cmd = 11, - automate_packet_cmd = 12, + automate_headers_request_cmd = 11, + automate_headers_reply_cmd = 12, + automate_command_cmd = 13, + automate_packet_cmd = 14, // usher commands // usher_cmd is sent either by a proxy that needs to know where @@ -208,6 +210,10 @@ public: id const & nonce1, rsa_oaep_sha_data & hmac_key_encrypted, rsa_sha1_signature & signature); + void read_automate_headers_request_cmd() const; + void write_automate_headers_request_cmd(); + void read_automate_headers_reply_cmd(std::vector > & headers) const; + void write_automate_headers_reply_cmd(std::vector > const & headers); void read_automate_command_cmd(std::vector & args, std::vector > & opts) const; void write_automate_command_cmd(std::vector const & args, ============================================================ --- network/automate_session.cc aa63e7329bf1e9ba3b3491e5ec07369f71c7941a +++ network/automate_session.cc eeb9c7d6c3b128d173544ea8210bb6efadb1a3cf @@ -74,7 +74,9 @@ void automate_session::accept_service() void automate_session::accept_service() { - send_command(); + netcmd cmd_out(get_version()); + cmd_out.write_automate_headers_request_cmd(); + write_netcmd(cmd_out); } string automate_session::usher_reply_data() const @@ -115,6 +117,26 @@ bool automate_session::do_work(transacti switch(cmd_in->get_cmd_code()) { + case automate_headers_request_cmd: + { + netcmd net_cmd(get_version()); + vector > headers; + commands::get_stdio_headers(headers); + net_cmd.write_automate_headers_reply_cmd(headers); + write_netcmd(net_cmd); + return true; + } + case automate_headers_reply_cmd: + { + vector > headers; + cmd_in->read_automate_headers_reply_cmd(headers); + + I(output_stream); + output_stream->write_headers(headers); + + send_command(); + return true; + } case automate_command_cmd: { options original_opts = app.opts;