Пример #1
0
static char* rep_str(char* instr)
{
	char* beg = strchr(instr, '[');
	if (!beg)
		return instr;

	char* end = strchr(beg+1, ']');

	for (size_t i = 0; i < sizeof(envvs)/sizeof(envvs[0]); i++){
		if (end)
			*end = '\0';

		if (strcmp(envvs[i], beg+1) != 0)
			continue;

		char* exp = arcan_expand_resource("", 1 << i);

		if (!exp)
			goto fail;

		if (!end){
			*beg = '\0';
			char* newstr = alloc_cat(instr, exp);
			free(instr);
			return newstr;
		}
		else{
			*beg = '\0';
			*end = '\0';
			char* newstr = alloc_cat(instr, exp);
			free(instr);
			char* resstr = alloc_cat(newstr, end+1);
			free(newstr);
			return rep_str(resstr);
		}
	}

fail:
	arcan_warning("expand failed, no match for supplied string (%s)\n", beg+1);
	return instr;
}
    static error forward_server_control_command(
        const std::string& _name,
        const std::string& _host,
        const std::string& _port_keyword,
        std::string&       _output ) {
        if ( EMPTY_RESC_HOST == _host ) {
            return SUCCESS();

        }

        int time_out = 0;
        error ret = get_server_property <
                    int > (
                        CFG_SERVER_CONTROL_PLANE_TIMEOUT,
                        time_out );
        if ( !ret.ok() ) {
            return PASS( ret );

        }

        int port = 0, num_hash_rounds = 0;
        std::string encryption_algorithm;
        buffer_crypt::array_t shared_secret;

        ret = get_server_properties(
                  _port_keyword,
                  port,
                  num_hash_rounds,
                  shared_secret,
                  encryption_algorithm );
        if ( !ret.ok() ) {
            return PASS( ret );

        }

        // stringify the port
        std::stringstream port_sstr;
        port_sstr << port;
        // standard zmq rep-req communication pattern
        zmq::context_t zmq_ctx( 1 );
        zmq::socket_t  zmq_skt( zmq_ctx, ZMQ_REQ );

        zmq_skt.setsockopt( ZMQ_RCVTIMEO, &time_out, sizeof( time_out ) );
        zmq_skt.setsockopt( ZMQ_SNDTIMEO, &time_out, sizeof( time_out ) );

        // this is the client so we connect rather than bind
        std::string conn_str( "tcp://" );
        conn_str += _host;
        conn_str += ":";
        conn_str += port_sstr.str();

        try {
            zmq_skt.connect( conn_str.c_str() );
        }
        catch ( zmq::error_t& e_ ) {
            std::string msg( "failed to connect to [" );
            msg + conn_str + "]";
            return ERROR(
                       SYS_INVALID_INPUT_PARAM,
                       msg );
        }


        // build the command to forward
        control_plane_command cmd;
        cmd.command = _name;
        cmd.options[ SERVER_CONTROL_OPTION_KW ] = SERVER_CONTROL_HOSTS_OPT;
        cmd.options[ SERVER_CONTROL_HOST_KW ]   = _host;

        // serialize using the generated avro class
        std::auto_ptr< avro::OutputStream > out = avro::memoryOutputStream();
        avro::EncoderPtr e = avro::binaryEncoder();
        e->init( *out );
        avro::encode( *e, cmd );
        boost::shared_ptr< std::vector< uint8_t > > data = avro::snapshot( *out );

        buffer_crypt crypt(
            shared_secret.size(),  // key size
            0,                     // salt size ( we dont send a salt )
            num_hash_rounds,       // num hash rounds
            encryption_algorithm.c_str() );

        buffer_crypt::array_t iv;
        buffer_crypt::array_t data_to_send;
        buffer_crypt::array_t data_to_encrypt(
            data->data(),
            data->data() + data->size() );
        ret = crypt.encrypt(
                  shared_secret,
                  iv,
                  data_to_encrypt,
                  data_to_send );
        if ( !ret.ok() ) {
            return PASS( ret );

        }

        // copy binary encoding into a zmq message for transport
        zmq::message_t rep( data_to_send.size() );
        memcpy(
            rep.data(),
            data_to_send.data(),
            data_to_send.size() );
        zmq_skt.send( rep );

        // wait for the server response
        zmq::message_t req;
        zmq_skt.recv( &req );

        if ( 0 == req.size() ) {
            return ERROR(
                       SYS_INVALID_INPUT_PARAM,
                       "empty response string" );

        }

        // decrypt the message before passing to avro
        buffer_crypt::array_t data_to_process;
        const uint8_t* data_ptr = static_cast< const uint8_t* >( req.data() );
        buffer_crypt::array_t data_to_decrypt(
            data_ptr,
            data_ptr + req.size() );
        ret = crypt.decrypt(
                  shared_secret,
                  iv,
                  data_to_decrypt,
                  data_to_process );
        if ( !ret.ok() ) {
            irods::log( PASS( ret ) );
            rodsLog( LOG_ERROR, "Failed to decrpyt [%s]", req.data() );
            return PASS( ret );

        }

        std::string rep_str(
            reinterpret_cast< char* >( data_to_process.data() ),
            data_to_process.size() );
        if ( SERVER_CONTROL_SUCCESS != rep_str ) {
            // check if the result is really an error or a status
            if ( std::string::npos == rep_str.find( "[-]" ) ) {
                _output += rep_str;

            }
            else {
                return ERROR(
                           CONTROL_PLANE_MESSAGE_ERROR,
                           rep_str );

            }
        }

        return SUCCESS();

    } // forward_server_control_command