<commit_before>#include "include/consul_admin.h"

//----------------------------HTTP Callbacks----------------------------------//

//This is the callback that gets called when we recieve the response to the
//Get Curl Request
size_t writeCallback(char * buf, size_t size, size_t nmemb, void* up)
{

  logging->debug("CONSUL: HTTP Query Callback Triggered");

//Put the response into a string
for (int c = 0; c<size*nmemb; c++)
{
	writedata.push_back(buf[c]);
}

return size*nmemb;
}

//--------------------------------Service-------------------------------------//

Service::Service()
{
  id="";
  name="";
  address="";
  port="";
}

Service::Service(std::string new_id, std::string new_name)
{
  id=new_id;
  name=new_name;
  address="";
  port="";
}

Service::Service(std::string new_id, std::string new_name, std::string new_address, std::string new_port)
{
  id=new_id;
  name=new_name;
  address=new_address;
  port=new_port;
}

Service::Service(std::string new_id, std::string new_name, std::string new_address, std::string new_port, std::vector<std::string> new_tags)
{
  id=new_id;
  name=new_name;
  address=new_address;
  port=new_port;
  tags=new_tags;
}

std::string Service::to_json()
{
  logging->debug("CONSUL: Service to JSON method Called:");
  logging->debug(id);

  //Initialize the string buffer and writer
  rapidjson::StringBuffer s;
  rapidjson::Writer<rapidjson::StringBuffer> writer(s);

  //Start writing the object

  writer.StartObject();

  writer.Key("ID");
  std::string id = id;
  writer.String( id.c_str(), (rapidjson::SizeType)id.length() );

  writer.Key("Name");
  std::string name = name;
  writer.String( name.c_str(), (rapidjson::SizeType)name.length() );

  writer.Key("Tags");
  std::string tag;
  writer.StartArray();
  for (int i=0; i<num_tags(); i++) {
    tag = tags[i];
    writer.String( tag.c_str(), (rapidjson::SizeType)tag.length() );
  }
  writer.EndArray();

  writer.Key("Address");
  std::string addr = address;
  writer.String( addr.c_str(), (rapidjson::SizeType)addr.length() );

  writer.Key("Port");
  std::string name = port;
  writer.String( port.c_str(), (rapidjson::SizeType)port.length() );

  writer.EndObject();

  //The Stringbuffer now contains a json message
  //of the object
	const char* ret_val = s.GetString();
	std::string ret_string (ret_val);
  logging->debug(ret_string);
  return ret_string;

}

//------------------------Consul Administrator--------------------------------//

//Put together a url query segment with the consul address provided at initialization
std::string ConsulAdmin::build_url(std::string request_url_segment)
{
  std::string url = consul_addr;
  url = url.append(request_url_segment);
  return url;
}

//Post a query to consul
std::string ConsulAdmin::query(std::string query_url)
{
  logging->info("CONSUL: Firing Query");
  logging->debug(query_url);
  //Clear the string that will hold the response data.
  writedata.clear();
  //Get the URL
  std::string url_string = build_url(query_url);
  const char * url_cstr = url_string.c_str();
  char *url = new char[url_string.length() + 1];
  strcpy(url, url_cstr);

  curl_easy_setopt(ha->get_instance(), CURLOPT_WRITEFUNCTION, &writeCallback);

  //Send the HTTP Request
  bool success = ha->get(url, timeout);
  delete url;
  if (success)
  {
    logging->debug("CONSUL: Query Successful");
    return writedata;
  }
  else
  {
    logging->debug("CONSUL: Query Failed");
    return "";
  }
}

//-------------------Service Registry Functions-------------------------------//

bool ConsulAdmin::register_service(Service& s)
{
  logging->debug("CONSUL: Registering Service");
  //Get the URL
  std::string url_string = build_url("/v1/agent/service/register");
  const char * url_cstr = url_string.c_str();
  char *url = new char[url_string.length() + 1];
  strcpy(url, url_cstr);

  //Get the message body
  std::string body_str = s.to_json();
  const char * body_cstr = body_str.c_str();
  char *body = new char[body_str.length() + 1];
  strcpy(body, body_cstr);

  //Send the HTTP Request
  bool success = ha->put(url, body, timeout);
  delete body;
  delete url;
  if (success)
  {
    logging->debug("CONSUL: Registration Successful");
  }
  else
  {
    logging->debug("CONSUL: Registration Unsuccessful");
  }
  return success;
}

bool ConsulAdmin::deregister_service(Service& s)
{
  //Get the URL
  std::string url_string = "/v1/agent/service/deregister/";
  url_string = url_string.append(id);
  url_string = build_url(url_string);
  const char * url_cstr = url_string.c_str();
  char *url = new char[url_string.length() + 1];
  strcpy(url, url_cstr);

  //Send the HTTP Request
  bool success = ha->put(url, "", timeout);
  delete url;
  if (success)
  {
    logging->debug("CONSUL: Deregistration Successful");
  }
  else
  {
    logging->debug("CONSUL: Deregistration Unsuccessful");
  }
  return success;
}

//----------------------------Basic Queries-----------------------------------//

std::string ConsulAdmin::datacenters()
{
  return query("/v1/catalog/datacenters");
}

std::string ConsulAdmin::nodes_dc(std::string data_center)
{
  std::string url = "/v1/catalog/nodes";
  if (!data_center.empty())
  {
    url = url.append("?dc=");
    url = url.append(data_center);
  }
  return query(url);
}

std::string ConsulAdmin::services_dc(std::string data_center)
{
  std::string url = "/v1/catalog/services";
  if (!data_center.empty())
  {
    url = url.append("?dc=");
    url = url.append(data_center);
  }
  return query(url);
}

std::string ConsulAdmin::nodes_service(std::string service)
{
  std::string url = "/v1/catalog/service/";
  url = url.append(service);
  return query(url);
}

std::string ConsulAdmin::services_node(std::string node, std::string data_center)
{
  std::string url = "/v1/catalog/node/";
  url = url.append(node);
  if (!data_center.empty())
  {
    url = url.append("?dc=");
    url = url.append(data_center);
  }
  return query(url);
}

//--------------Configuration Key-Value Storage Functions---------------------//

bool ConsulAdmin::set_config_value(std::string key, std::string val)
{
  logging->info("CONSUL: Setting Configuration Value");
  logging->debug(key);
  logging->debug(val);
  //Get the URL
  std::string url_string = build_url("/v1/kv/");
  url_string = url_string.append(key);
  const char * url_cstr = url_string.c_str();
  char *url = new char[url_string.length() + 1];
  strcpy(url, url_cstr);

  //Get the message body
  const char * body_cstr = val.c_str();
  char *body = new char[val.length() + 1];
  strcpy(body, body_cstr);

  //Send the HTTP Request
  bool success = ha->put(url, data, timeout);
  delete body;
  delete url;
  if (success)
  {
    logging->debug("CONSUL: Config Value Set Successful");
  }
  else
  {
    logging->debug("CONSUL: Config Value Set Unsuccessful");
  }
  return success;
}

std::string ConsulAdmin::get_config_value(std::string key)
{
  std::string url = "/v1/kv/";
  url = url.append(key);
  if (!data_center.empty())
  {
    url = url.append("?dc=");
    url = url.append(data_center);
  }
  return query(url);
}

bool ConsulAdmin::del_config_value(std::string key)
{
  logging->info("CONSUL: Deleting Configuration Value");
  logging->debug(key);
  //Get the URL
  std::string url_string = build_url("/v1/kv/");
  url_string = url_string.append(key);
  const char * url_cstr = url_string.c_str();
  char *url = new char[url_string.length() + 1];
  strcpy(url, url_cstr);

  //Send the HTTP Request
  bool success = ha->del(url, timeout);
  delete url;
  if (success)
  {
    logging->debug("CONSUL: Config Value Delete Successful");
  }
  else
  {
    logging->debug("CONSUL: Config Value Delete Unsuccessful");
  }
  return success;
}
<commit_msg>Consul Admin Fixes<commit_after>#include "include/consul_admin.h"

//----------------------------HTTP Callbacks----------------------------------//

//This is the callback that gets called when we recieve the response to the
//Get Curl Request
size_t writeCallback(char * buf, size_t size, size_t nmemb, void* up)
{

  logging->debug("CONSUL: HTTP Query Callback Triggered");

//Put the response into a string
for (int c = 0; c<size*nmemb; c++)
{
	writedata.push_back(buf[c]);
}

return size*nmemb;
}

//--------------------------------Service-------------------------------------//

Service::Service()
{
  id="";
  name="";
  address="";
  port="";
}

Service::Service(std::string new_id, std::string new_name)
{
  id=new_id;
  name=new_name;
  address="";
  port="";
}

Service::Service(std::string new_id, std::string new_name, std::string new_address, std::string new_port)
{
  id=new_id;
  name=new_name;
  address=new_address;
  port=new_port;
}

Service::Service(std::string new_id, std::string new_name, std::string new_address, std::string new_port, std::vector<std::string> new_tags)
{
  id=new_id;
  name=new_name;
  address=new_address;
  port=new_port;
  tags=new_tags;
}

std::string Service::to_json()
{
  logging->debug("CONSUL: Service to JSON method Called:");
  logging->debug(id);

  //Initialize the string buffer and writer
  rapidjson::StringBuffer s;
  rapidjson::Writer<rapidjson::StringBuffer> writer(s);

  //Start writing the object

  writer.StartObject();

  writer.Key("ID");
  std::string id = id;
  writer.String( id.c_str(), (rapidjson::SizeType)id.length() );

  writer.Key("Name");
  std::string name = name;
  writer.String( name.c_str(), (rapidjson::SizeType)name.length() );

  writer.Key("Tags");
  std::string tag;
  writer.StartArray();
  for (int i=0; i<num_tags(); i++) {
    tag = tags[i];
    writer.String( tag.c_str(), (rapidjson::SizeType)tag.length() );
  }
  writer.EndArray();

  writer.Key("Address");
  std::string addr = address;
  writer.String( addr.c_str(), (rapidjson::SizeType)addr.length() );

  writer.Key("Port");
  std::string p = port;
  writer.String( p.c_str(), (rapidjson::SizeType)p.length() );

  writer.EndObject();

  //The Stringbuffer now contains a json message
  //of the object
	const char* ret_val = s.GetString();
	std::string ret_string (ret_val);
  logging->debug(ret_string);
  return ret_string;

}

//------------------------Consul Administrator--------------------------------//

//Put together a url query segment with the consul address provided at initialization
std::string ConsulAdmin::build_url(std::string request_url_segment)
{
  std::string url = consul_addr;
  url = url.append(request_url_segment);
  return url;
}

//Post a query to consul
std::string ConsulAdmin::query(std::string query_url)
{
  logging->info("CONSUL: Firing Query");
  logging->debug(query_url);
  //Clear the string that will hold the response data.
  writedata.clear();
  //Get the URL
  std::string url_string = build_url(query_url);
  const char * url_cstr = url_string.c_str();
  char *url = new char[url_string.length() + 1];
  strcpy(url, url_cstr);

  curl_easy_setopt(ha->get_instance(), CURLOPT_WRITEFUNCTION, &writeCallback);

  //Send the HTTP Request
  bool success = ha->get(url, timeout);
  delete url;
  if (success)
  {
    logging->debug("CONSUL: Query Successful");
    return writedata;
  }
  else
  {
    logging->debug("CONSUL: Query Failed");
    return "";
  }
}

//-------------------Service Registry Functions-------------------------------//

bool ConsulAdmin::register_service(Service& s)
{
  logging->debug("CONSUL: Registering Service");
  //Get the URL
  std::string url_string = build_url("/v1/agent/service/register");
  const char * url_cstr = url_string.c_str();
  char *url = new char[url_string.length() + 1];
  strcpy(url, url_cstr);

  //Get the message body
  std::string body_str = s.to_json();
  const char * body_cstr = body_str.c_str();
  char *body = new char[body_str.length() + 1];
  strcpy(body, body_cstr);

  //Send the HTTP Request
  bool success = ha->put(url, body, timeout);
  delete body;
  delete url;
  if (success)
  {
    logging->debug("CONSUL: Registration Successful");
  }
  else
  {
    logging->debug("CONSUL: Registration Unsuccessful");
  }
  return success;
}

bool ConsulAdmin::deregister_service(Service& s)
{
  //Get the URL
  std::string url_string = "/v1/agent/service/deregister/";
  url_string = url_string.append(s.get_id());
  url_string = build_url(url_string);
  const char * url_cstr = url_string.c_str();
  char *url = new char[url_string.length() + 1];
  strcpy(url, url_cstr);

  //Send the HTTP Request
  bool success = ha->put(url, "", timeout);
  delete url;
  if (success)
  {
    logging->debug("CONSUL: Deregistration Successful");
  }
  else
  {
    logging->debug("CONSUL: Deregistration Unsuccessful");
  }
  return success;
}

//----------------------------Basic Queries-----------------------------------//

std::string ConsulAdmin::datacenters()
{
  return query("/v1/catalog/datacenters");
}

std::string ConsulAdmin::nodes_dc(std::string data_center)
{
  std::string url = "/v1/catalog/nodes";
  if (!data_center.empty())
  {
    url = url.append("?dc=");
    url = url.append(data_center);
  }
  return query(url);
}

std::string ConsulAdmin::services_dc(std::string data_center)
{
  std::string url = "/v1/catalog/services";
  if (!data_center.empty())
  {
    url = url.append("?dc=");
    url = url.append(data_center);
  }
  return query(url);
}

std::string ConsulAdmin::nodes_service(std::string service)
{
  std::string url = "/v1/catalog/service/";
  url = url.append(service);
  return query(url);
}

std::string ConsulAdmin::services_node(std::string node, std::string data_center)
{
  std::string url = "/v1/catalog/node/";
  url = url.append(node);
  if (!data_center.empty())
  {
    url = url.append("?dc=");
    url = url.append(data_center);
  }
  return query(url);
}

//--------------Configuration Key-Value Storage Functions---------------------//

bool ConsulAdmin::set_config_value(std::string key, std::string val)
{
  logging->info("CONSUL: Setting Configuration Value");
  logging->debug(key);
  logging->debug(val);
  //Get the URL
  std::string url_string = build_url("/v1/kv/");
  url_string = url_string.append(key);
  const char * url_cstr = url_string.c_str();
  char *url = new char[url_string.length() + 1];
  strcpy(url, url_cstr);

  //Get the message body
  const char * body_cstr = val.c_str();
  char *body = new char[val.length() + 1];
  strcpy(body, body_cstr);

  //Send the HTTP Request
  bool success = ha->put(url, body, timeout);
  delete body;
  delete url;
  if (success)
  {
    logging->debug("CONSUL: Config Value Set Successful");
  }
  else
  {
    logging->debug("CONSUL: Config Value Set Unsuccessful");
  }
  return success;
}

std::string ConsulAdmin::get_config_value(std::string key)
{
  std::string url = "/v1/kv/";
  url = url.append(key);
  return query(url);
}

bool ConsulAdmin::del_config_value(std::string key)
{
  logging->info("CONSUL: Deleting Configuration Value");
  logging->debug(key);
  //Get the URL
  std::string url_string = build_url("/v1/kv/");
  url_string = url_string.append(key);
  const char * url_cstr = url_string.c_str();
  char *url = new char[url_string.length() + 1];
  strcpy(url, url_cstr);

  //Send the HTTP Request
  bool success = ha->del(url, timeout);
  delete url;
  if (success)
  {
    logging->debug("CONSUL: Config Value Delete Successful");
  }
  else
  {
    logging->debug("CONSUL: Config Value Delete Unsuccessful");
  }
  return success;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>

#include "include/factory.h"

#include "include/factory/commandline_interface.h"
#include "include/factory/consul_interface.h"
#include "include/factory/couchbase_interface.h"
#include "include/factory/http_interface.h"
#include "include/factory/logging_interface.h"
#include "include/factory/redis_interface.h"
#include "include/factory/uuid_interface.h"
#include "include/factory/zmq_interface.h"

int main( int argc, char** argv )
{

ServiceComponentFactory factory;

//! Get a Logging Interface instance
std::string initFileName = "test/log4cpp_test.properties";
logging = factory.get_logging_interface( initFileName );

CommandLineInterface *cli = factory.get_command_line_interface(argc, argv);

uuidInterface *uuid = factory.get_uuid_interface();

//! Get the HTTP Interface instance
HttpInterface *ha = factory.get_http_interface();

//! Get a Service Interface instance
ServiceInterface *s = factory.get_service_interface();

//! Get a Consul Interface instance
ConsulInterface *consul = factory.get_consul_interface( "localhost:8500" );

//! Get a Couchbase Interface instance
CouchbaseInterface *ca = factory.get_couchbase_interface( "couchbase://localhost/default" );

//! Get a Couchbase Interface instance for a password protected DB
//CouchbaseInterface *ca2 = factory.get_couchbase_interface( const char * conn, const char * pswd );

//! Get a Redis Cluster Interface instance
std::vector<RedisConnChain> RedisConnectionList;
RedisConnChain r;
r.ip = "127.0.0.1";
r.port = 7000;
r.password = "";
r.pool_size = 2;
r.timeout = 5;
r.role = 0;
RedisConnectionList.push_back(r);
RedisInterface *ra = factory.get_redis_cluster_interface( RedisConnectionList );

//! Get a ZMQ Outbound Interface instance
ZmqOut *zmqo = factory.get_zmq_outbound_interface( "tcp://localhost:5555" );

//! Get a ZMQ Inbound Interface instance
ZmqIn *zmqi = factory.get_zmq_inbound_interface( "tcp://*:5555" )

//Run our tests

//Command Line Tests
std::cout << cli->get_program_name() << std::endl;
if ( cli->opt_exist("name") ) {
  std::cout << cli->get_opt("name") << std::endl;
}

delete cli;
delete uuid;
delete ha;
delete s;
delete consul;
delete ca;
delete ca2;
delete ra;
delete logging;
delete zmqo;
delete zmqi;

return 0;
}
<commit_msg>Factory Implementation Fixes<commit_after>#include <iostream>
#include <string>

#include "include/factory.h"

#include "include/factory/commandline_interface.h"
#include "include/factory/consul_interface.h"
#include "include/factory/couchbase_interface.h"
#include "include/factory/http_interface.h"
#include "include/factory/logging_interface.h"
#include "include/factory/redis_interface.h"
#include "include/factory/uuid_interface.h"
#include "include/factory/zmq_interface.h"

int main( int argc, char** argv )
{

ServiceComponentFactory factory;

//! Get a Logging Interface instance
std::string initFileName = "test/log4cpp_test.properties";
logging = factory.get_logging_interface( initFileName );

CommandLineInterface *cli = factory.get_command_line_interface(argc, argv);

uuidInterface *uuid = factory.get_uuid_interface();

//! Get the HTTP Interface instance
HttpInterface *ha = factory.get_http_interface();

//! Get a Service Interface instance
ServiceInterface *s = factory.get_service_interface();

//! Get a Consul Interface instance
ConsulInterface *consul = factory.get_consul_interface( "localhost:8500" );

//! Get a Couchbase Interface instance
CouchbaseInterface *ca = factory.get_couchbase_interface( "couchbase://localhost/default" );

//! Get a Couchbase Interface instance for a password protected DB
//CouchbaseInterface *ca2 = factory.get_couchbase_interface( const char * conn, const char * pswd );

//! Get a Redis Cluster Interface instance
std::vector<RedisConnChain> RedisConnectionList;
RedisConnChain r;
r.ip = "127.0.0.1";
r.port = 7000;
r.password = "";
r.pool_size = 2;
r.timeout = 5;
r.role = 0;
RedisConnectionList.push_back(r);
RedisInterface *ra = factory.get_redis_cluster_interface( RedisConnectionList );

//! Get a ZMQ Outbound Interface instance
Zmqio *zmqo = factory.get_zmq_outbound_interface( "tcp://localhost:5555" );

//! Get a ZMQ Inbound Interface instance
Zmqio *zmqi = factory.get_zmq_inbound_interface( "tcp://*:5555" );

//Run our tests

//Command Line Tests
std::cout << cli->get_program_name() << std::endl;
if ( cli->opt_exist("name") ) {
  std::cout << cli->get_opt("name") << std::endl;
}

delete cli;
delete uuid;
delete ha;
delete s;
delete consul;
delete ca;
delete ca2;
delete ra;
delete logging;
delete zmqo;
delete zmqi;

return 0;
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <cpprest/json.h>
#include <cpprest/uri.h>
#include <string>
#include <windows.h>
#include "Base64.h"
#include "StringUtils.h"
#include "REST.h"
#include "Gzip.h"
#include "QueryCache.h"
#include "JsonConverter.h"

#include <ctime>
#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdarg.h>

using namespace utility;
using namespace web::http;
using namespace web::http::client;
using namespace concurrency::streams;
using namespace web;
using namespace web::json;

/// <summary>
/// Find the longest length
/// </summary>
/// <param name="results"></param>
/// <param name="column"></param>
/// <returns></returns>
int ScanForLength ( std::vector <SQLRowContent*> results, int column )
{
    int max = 0;

    for ( auto p = results . begin (); p < results . end (); p++ )
    {
        SQLRowContent* result = *p;
        int length = result -> contents[column] . size ();

        if ( length > max )
        {
            max = length;
        }
    }

    return max;
}

/// <summary>
/// Scale is Maximum number of digits to the right of the decimal point.
/// Find the largest scale.
/// </summary>
/// <param name="results"></param>
/// <param name="column"></param>
/// <returns></returns>
int ScanForScale ( std::vector <SQLRowContent*> results, int column )
{
    int max = 0;

    for ( auto p = results . begin (); p < results . end (); p++ )
    {
        SQLRowContent* result = *p;
        int length = result -> contents[column] . size ();
        int dotLocation = result -> contents[column] . find ( L"." );

        if ( dotLocation != string::npos )
        {
            int scale = length - 1 - dotLocation;

            if ( scale > max )
            {
                max = scale;
            }
        }
    }

    return max;
}

void overwrite ( SQLResponse* res )
{
    for ( int i = 0; i < ( int ) res -> columnMetas . size (); ++i )
    {
        SelectedColumnMeta* meta = res -> columnMetas[i];
        ODBCTypes t = ( ODBCTypes ) meta -> columnType;
        int scale = 0;
        int length = 0;

        switch ( t )
        {
            case ODBCTypes::ODBC_Numeric :
            case ODBCTypes::ODBC_Decimal :
            case ODBCTypes::ODBC_Double :
            case ODBCTypes::ODBC_Real :
            case ODBCTypes::ODBC_Float :
                scale = ScanForScale ( res -> results, i );
                meta -> scale = scale;
                meta -> scale = 4;
                break;

            case ODBCTypes::ODBC_Char :
            case ODBCTypes::ODBC_VarChar :
            case ODBCTypes::ODBC_LongVarChar :
            case ODBCTypes::ODBC_WChar :
            case ODBCTypes::ODBC_WVarChar :
            case ODBCTypes::ODBC_WLongVarChar :
            case ODBCTypes::ODBC_DateTime :
            case ODBCTypes::ODBC_Type_Date :
            case ODBCTypes::ODBC_Type_Time :
            case ODBCTypes::ODBC_Type_Timestamp :
                length = ScanForLength ( res -> results, i );
				if (length > meta -> displaySize)
				{
					meta -> displaySize = length;
				}

				if (length > meta -> precision)
				{
					meta -> precision = length;
				}
                break;

            default :
                break;
        }
    }
}

std::wstring completeServerStr ( char* serverStr, long port )
{
    //concat the whole server string
    char completeServerAddr[256];
    char portSuffix[10];
    sprintf ( portSuffix, ":%d", port );

    if ( strstr ( serverStr, "https://" ) == serverStr ||
        strstr ( serverStr, "http://" ) == serverStr )
    {
        sprintf ( completeServerAddr, "%s", serverStr );
    }

    else
    {
        // by default use https
        sprintf ( completeServerAddr, "https://%s", serverStr );
    }

    if ( strstr ( serverStr, portSuffix ) == NULL )
    {
        strcat ( completeServerAddr, portSuffix );
    }

    return string2wstring ( std::string ( completeServerAddr ) );
}

http_request makeRequest ( const char* username, const char* passwd, const wchar_t* uriStr, http::method method )
{
    http_request request;
    char s[128];
    sprintf ( s, "%s:%s", username, passwd );
    std::string b64 = base64_encode ( ( unsigned char const* ) s, strlen ( s ) );
    request . set_method ( method );
    request . set_request_uri ( uri ( uri::encode_uri ( uriStr ) ) );
    request . headers () . add ( header_names::authorization, string2wstring ( "Basic " + b64 ) );
	request . headers () . add ( header_names::accept, "application/json" );
    request . headers () . add ( header_names::content_type, "application/json" );
    return request;
}

bool restAuthenticate ( char* serverAddr, long port, char* username, char* passwd )
{
    wstring serverAddrW = completeServerStr ( serverAddr, port );
    http_client_config config;
    config . set_timeout ( utility::seconds ( 300 ) );
    http_client session ( serverAddrW, config );
    //can get project list only when correct username/password is given
    http_request request = makeRequest ( username, passwd, L"/kylin/api/projects", methods::GET );
    http_response response = session . request ( request ) . get ();

    if ( response . status_code () == status_codes::OK )
    {
        return true;
    }

    else
    {
        return false;
    }
}

void restListProjects ( char* serverAddr, long port, char* username, char* passwd, std::vector <string>& holder )
{
    wstring serverAddrW = completeServerStr ( serverAddr, port );
    http_client_config config;
    config . set_timeout ( utility::seconds ( 300 ) );
    http_client session ( serverAddrW, config );
    http_request request = makeRequest ( username, passwd, L"/kylin/api/projects", methods::GET );
    http_response response = session . request ( request ) . get ();

    if ( response . status_code () == status_codes::OK )
    {
        web::json::value projects = response . extract_json () . get ();

        for ( auto iter = projects . as_array () . begin (); iter != projects . as_array () . end (); ++iter )
        {
            holder . push_back ( wstring2string ( ( *iter )[U ( "name" )] . as_string () ) );
        }

        if ( holder . size () == 0 )
        {
            throw exception ( "There is no project available in this server" );
        }
    }

    else if ( response . status_code () == status_codes::InternalError )
    {
        std::unique_ptr <ErrorMessage> em = ErrorMessageFromJSON ( response . extract_json () . get () );
        string errorMsg = wstring2string ( em -> msg );
        throw exception ( errorMsg . c_str () );
    }

    else
    {
        throw exception ( "REST request(listproject) Invalid Response status code : " + response . status_code () );
    }
}

std::unique_ptr <MetadataResponse> restGetMeta ( char* serverAddr, long port, char* username, char* passwd,
                                                 char* project )
{
    wstring serverAddrW = completeServerStr ( serverAddr, port );
    http_client_config config;
    config . set_timeout ( utility::seconds ( 300 ) );
    http_client session ( serverAddrW, config );
    std::wstringstream wss;
    wss << L"/kylin/api/tables_and_columns" << L"?project=" << project;
    http_request request = makeRequest ( username, passwd, wss . str () . c_str (), methods::GET );
    http_response response = session . request ( request ) . get ();

    if ( response . status_code () == status_codes::OK )
    {
        return MetadataResponseFromJSON ( response . extract_json () . get () );
    }

    else if ( response . status_code () == status_codes::Unauthorized )
    {
        throw exception ( "Username/Password Unauthorized." );
    }

    else if ( response . status_code () == status_codes::InternalError )
    {
        std::unique_ptr <ErrorMessage> em = ErrorMessageFromJSON ( response . extract_json () . get () );
        string errorMsg = wstring2string ( em -> msg );
        throw exception ( errorMsg . c_str () );
    }

    else
    {
        throw exception ( "REST request(getmeta) Invalid Response status code : " + response . status_code () );
    }
}

wstring cookQuery ( wchar_t* p )
{
    std::wstringstream wss;

	int l = wcslen ( p );
    for ( int i = 0; i < l; i++ )
    {
        if ( p[i] == L'\r' || p[i] == L'\n' || p[i] == L'\t' )
        {
            wss << L' ';
        }

        else if (p[i] == L'"')
		{
			wss << L"\\\"";
		}

		else
		{
			wss << p[i];
		}
    }

	return wss.str();
}

wstring getBodyString ( http_response& response )
{
    bool isGzipped = response . headers () . has ( L"Content-Encoding" );

    if ( isGzipped )
    {
        isGzipped = false;
        http_headers::iterator iterator = response . headers () . find ( L"Content-Encoding" );

        if ( iterator != response . headers () . end () )
        {
            wstring contentEncoding = iterator -> second;

            if ( contentEncoding . find ( L"gzip" ) != std::string::npos )
            {
                isGzipped = true;
            }
        }
    }

    container_buffer <std::string> bodyBuffer;
    response . body () . read_to_end ( bodyBuffer ) . get ();
    const std::string& raw = bodyBuffer . collection ();
    std::string uncompressed;

    if ( isGzipped )
    {
        bool decompressStatus = gzipInflate ( raw, uncompressed );

        if ( !decompressStatus )
        {
            throw exception ( "gzip decompress failed" );
        }
    }

    else
    {
        uncompressed = raw;
    }

    //convert the string from utf8 to wchar
    int size_needed = ::MultiByteToWideChar ( CP_UTF8, 0, ( char* ) uncompressed . c_str (), uncompressed . size (), NULL, 0 );
    std::wstring ret ( size_needed, 0 );
    ::MultiByteToWideChar ( CP_UTF8, 0, ( char* ) uncompressed . c_str (), uncompressed . size (), &ret[0], size_needed );
    return ret;
}

std::unique_ptr <SQLResponse> convertToSQLResponse ( int statusFlag,
										  wstring responseStr )
{
    if ( statusFlag == 1 )
    {
        //convert to json
        web::json::value actualRes = web::json::value::parse ( responseStr );
        std::unique_ptr <SQLResponse> r = SQLResponseFromJSON ( actualRes );

        if ( r -> isException == true )
        {
            string expMsg = wstring2string ( r -> exceptionMessage );
            throw exception ( expMsg . c_str () );
        }

        overwrite ( r . get () );
        return r;
    }

    else if ( statusFlag == 0 )
    {
        std::unique_ptr <ErrorMessage> em = ErrorMessageFromJSON ( web::json::value::parse ( responseStr ) );
        string expMsg = wstring2string ( em -> msg );
        throw exception ( expMsg . c_str () );
    }

    return NULL;
}

wstring requestQuery ( wchar_t* rawSql, char* serverAddr, long port, char* username,
                                          char* passwd,
                                          char* project,
										  bool isPrepare,
										  int* statusFlag)
{
    //using local cache to intercept probing queries
    const wchar_t* cachedQueryRes = NULL;

	if (isPrepare) {
		cachedQueryRes = loadCache ( rawSql  );
	}

    if ( cachedQueryRes != NULL )
    {
		*statusFlag = 1;
        return cachedQueryRes;
    }

    //real requesting
    wstring serverAddrW = completeServerStr ( serverAddr, port );
    http_client_config config;
    config . set_timeout ( utility::seconds ( 36000 ) );

	//uncomment these lines for debug with proxy
	//wstring p = L"http://127.0.0.1:8888";
	//config.set_proxy(web_proxy(p));

    http_client session ( serverAddrW, config );
    http_request request;

	if (!isPrepare)
	{
		request = makeRequest ( username, passwd, L"/kylin/api/query", methods::POST );
	}

	else
	{
		request = makeRequest ( username, passwd, L"/kylin/api/query/prestate", methods::POST );
	}

    wstring sql = cookQuery ( rawSql );
    std::wstringstream wss;
    wss << L"{ \"acceptPartial\": false, \"project\" : \"" << project << L"\", " << " \"sql\" : \"" << sql << L"\" }" ;
    request . set_body ( wss . str (), L"application/json" );
    request . headers () . add ( header_names::accept_encoding, "gzip,deflate" );
    http_response response;
	http::status_code status;

	try
    {
        response = session . request ( request ) . get ();
        status = response . status_code ();
    }

    catch ( std::exception& e )
    {
        std::stringstream ss;
        ss << "An exception is throw Error message: " << e . what ();
        throw exception ( ss . str () . c_str () );
    }

	if ( status == status_codes::OK )
    {
        *statusFlag = 1;
    }

    else if ( status == status_codes::InternalError )
    {
        *statusFlag = 0;
    }

    else
    {
        throw exception ( "Unknown exception in rest query with return code " + status );
    }

	wstring ret = getBodyString ( response );

    if (*statusFlag == 1 && isPrepare)
    {
        storeCache(rawSql, ret.c_str());
    }
	return ret;
}

<commit_msg>minor, fix ODBC for backward compatible support<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <cpprest/json.h>
#include <cpprest/uri.h>
#include <string>
#include <windows.h>
#include "Base64.h"
#include "StringUtils.h"
#include "REST.h"
#include "Gzip.h"
#include "QueryCache.h"
#include "JsonConverter.h"

#include <ctime>
#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdarg.h>

using namespace utility;
using namespace web::http;
using namespace web::http::client;
using namespace concurrency::streams;
using namespace web;
using namespace web::json;

/// <summary>
/// Find the longest length
/// </summary>
/// <param name="results"></param>
/// <param name="column"></param>
/// <returns></returns>
int ScanForLength ( std::vector <SQLRowContent*> results, int column )
{
    int max = 0;

    for ( auto p = results . begin (); p < results . end (); p++ )
    {
        SQLRowContent* result = *p;
        int length = result -> contents[column] . size ();

        if ( length > max )
        {
            max = length;
        }
    }

    return max;
}

/// <summary>
/// Scale is Maximum number of digits to the right of the decimal point.
/// Find the largest scale.
/// </summary>
/// <param name="results"></param>
/// <param name="column"></param>
/// <returns></returns>
int ScanForScale ( std::vector <SQLRowContent*> results, int column )
{
    int max = 0;

    for ( auto p = results . begin (); p < results . end (); p++ )
    {
        SQLRowContent* result = *p;
        int length = result -> contents[column] . size ();
        int dotLocation = result -> contents[column] . find ( L"." );

        if ( dotLocation != string::npos )
        {
            int scale = length - 1 - dotLocation;

            if ( scale > max )
            {
                max = scale;
            }
        }
    }

    return max;
}

void overwrite ( SQLResponse* res )
{
    for ( int i = 0; i < ( int ) res -> columnMetas . size (); ++i )
    {
        SelectedColumnMeta* meta = res -> columnMetas[i];
        ODBCTypes t = ( ODBCTypes ) meta -> columnType;
        int scale = 0;
        int length = 0;

        switch ( t )
        {
            case ODBCTypes::ODBC_Numeric :
            case ODBCTypes::ODBC_Decimal :
            case ODBCTypes::ODBC_Double :
            case ODBCTypes::ODBC_Real :
            case ODBCTypes::ODBC_Float :
                scale = ScanForScale ( res -> results, i );
                meta -> scale = scale;
                meta -> scale = 4;
                break;

            case ODBCTypes::ODBC_Char :
            case ODBCTypes::ODBC_VarChar :
            case ODBCTypes::ODBC_LongVarChar :
            case ODBCTypes::ODBC_WChar :
            case ODBCTypes::ODBC_WVarChar :
            case ODBCTypes::ODBC_WLongVarChar :
            case ODBCTypes::ODBC_DateTime :
            case ODBCTypes::ODBC_Type_Date :
            case ODBCTypes::ODBC_Type_Time :
            case ODBCTypes::ODBC_Type_Timestamp :
                length = ScanForLength ( res -> results, i );
				if (length > meta -> displaySize)
				{
					meta -> displaySize = length;
				}

				if (length > meta -> precision)
				{
					meta -> precision = length;
				}
                break;

            default :
                break;
        }
    }
}

std::wstring completeServerStr ( char* serverStr, long port )
{
    //concat the whole server string
    char completeServerAddr[256];
    char portSuffix[10];
    sprintf ( portSuffix, ":%d", port );

    if ( strstr ( serverStr, "https://" ) == serverStr ||
        strstr ( serverStr, "http://" ) == serverStr )
    {
        sprintf ( completeServerAddr, "%s", serverStr );
    }

    else
    {
        // by default use https
        sprintf ( completeServerAddr, "https://%s", serverStr );
    }

    if ( strstr ( serverStr, portSuffix ) == NULL )
    {
        strcat ( completeServerAddr, portSuffix );
    }

    return string2wstring ( std::string ( completeServerAddr ) );
}

http_request makeRequest ( const char* username, const char* passwd, const wchar_t* uriStr, http::method method )
{
    http_request request;
    char s[128];
    sprintf ( s, "%s:%s", username, passwd );
    std::string b64 = base64_encode ( ( unsigned char const* ) s, strlen ( s ) );
    request . set_method ( method );
    request . set_request_uri ( uri ( uri::encode_uri ( uriStr ) ) );
    request . headers () . add ( header_names::authorization, string2wstring ( "Basic " + b64 ) );
	request . headers () . add ( header_names::accept, "application/json" );
    request . headers () . add ( header_names::content_type, "application/json" );
    return request;
}

bool restAuthenticate ( char* serverAddr, long port, char* username, char* passwd )
{
    wstring serverAddrW = completeServerStr ( serverAddr, port );
    http_client_config config;
    config . set_timeout ( utility::seconds ( 300 ) );
    http_client session ( serverAddrW, config );
    //can get project list only when correct username/password is given
    http_request request = makeRequest ( username, passwd, L"/kylin/api/projects", methods::GET );
    http_response response = session . request ( request ) . get ();

    if ( response . status_code () == status_codes::OK )
    {
        return true;
    }

    else
    {
        return false;
    }
}

void restListProjects ( char* serverAddr, long port, char* username, char* passwd, std::vector <string>& holder )
{
    wstring serverAddrW = completeServerStr ( serverAddr, port );
    http_client_config config;
    config . set_timeout ( utility::seconds ( 300 ) );
    http_client session ( serverAddrW, config );
    http_request request = makeRequest ( username, passwd, L"/kylin/api/projects", methods::GET );
    http_response response = session . request ( request ) . get ();

    if ( response . status_code () == status_codes::OK )
    {
        web::json::value projects = response . extract_json () . get ();

        for ( auto iter = projects . as_array () . begin (); iter != projects . as_array () . end (); ++iter )
        {
            holder . push_back ( wstring2string ( ( *iter )[U ( "name" )] . as_string () ) );
        }

        if ( holder . size () == 0 )
        {
            throw exception ( "There is no project available in this server" );
        }
    }

    else if ( response . status_code () == status_codes::InternalError )
    {
        std::unique_ptr <ErrorMessage> em = ErrorMessageFromJSON ( response . extract_json () . get () );
        string errorMsg = wstring2string ( em -> msg );
        throw exception ( errorMsg . c_str () );
    }

    else
    {
        throw exception ( "REST request(listproject) Invalid Response status code : " + response . status_code () );
    }
}

std::unique_ptr <MetadataResponse> restGetMeta ( char* serverAddr, long port, char* username, char* passwd,
                                                 char* project )
{
    wstring serverAddrW = completeServerStr ( serverAddr, port );
    http_client_config config;
    config . set_timeout ( utility::seconds ( 300 ) );
    http_client session ( serverAddrW, config );
    std::wstringstream wss;
    wss << L"/kylin/api/tables_and_columns" << L"?project=" << project;
    http_request request = makeRequest ( username, passwd, wss . str () . c_str (), methods::GET );
    http_response response = session . request ( request ) . get ();

    if ( response . status_code () == status_codes::OK )
    {
        return MetadataResponseFromJSON ( response . extract_json () . get () );
    }

    else if ( response . status_code () == status_codes::Unauthorized )
    {
        throw exception ( "Username/Password Unauthorized." );
    }

    else if ( response . status_code () == status_codes::InternalError )
    {
        std::unique_ptr <ErrorMessage> em = ErrorMessageFromJSON ( response . extract_json () . get () );
        string errorMsg = wstring2string ( em -> msg );
        throw exception ( errorMsg . c_str () );
    }

    else
    {
        throw exception ( "REST request(getmeta) Invalid Response status code : " + response . status_code () );
    }
}

wstring cookQuery ( wchar_t* p )
{
    std::wstringstream wss;

	int l = wcslen ( p );
    for ( int i = 0; i < l; i++ )
    {
        if ( p[i] == L'\r' || p[i] == L'\n' || p[i] == L'\t' )
        {
            wss << L' ';
        }

        else if (p[i] == L'"')
		{
			wss << L"\\\"";
		}

		else
		{
			wss << p[i];
		}
    }

	return wss.str();
}

wstring getBodyString ( http_response& response )
{
    bool isGzipped = response . headers () . has ( L"Content-Encoding" );

    if ( isGzipped )
    {
        isGzipped = false;
        http_headers::iterator iterator = response . headers () . find ( L"Content-Encoding" );

        if ( iterator != response . headers () . end () )
        {
            wstring contentEncoding = iterator -> second;

            if ( contentEncoding . find ( L"gzip" ) != std::string::npos )
            {
                isGzipped = true;
            }
        }
    }

    container_buffer <std::string> bodyBuffer;
    response . body () . read_to_end ( bodyBuffer ) . get ();
    const std::string& raw = bodyBuffer . collection ();
    std::string uncompressed;

    if ( isGzipped )
    {
        bool decompressStatus = gzipInflate ( raw, uncompressed );

        if ( !decompressStatus )
        {
            throw exception ( "gzip decompress failed" );
        }
    }

    else
    {
        uncompressed = raw;
    }

    //convert the string from utf8 to wchar
    int size_needed = ::MultiByteToWideChar ( CP_UTF8, 0, ( char* ) uncompressed . c_str (), uncompressed . size (), NULL, 0 );
    std::wstring ret ( size_needed, 0 );
    ::MultiByteToWideChar ( CP_UTF8, 0, ( char* ) uncompressed . c_str (), uncompressed . size (), &ret[0], size_needed );
    return ret;
}

std::unique_ptr <SQLResponse> convertToSQLResponse ( int statusFlag,
										  wstring responseStr )
{
    if ( statusFlag == 1 )
    {
        //convert to json
        web::json::value actualRes = web::json::value::parse ( responseStr );
        std::unique_ptr <SQLResponse> r = SQLResponseFromJSON ( actualRes );

        if ( r -> isException == true )
        {
            string expMsg = wstring2string ( r -> exceptionMessage );
            throw exception ( expMsg . c_str () );
        }

        overwrite ( r . get () );
        return r;
    }

    else if ( statusFlag == 0 )
    {
        std::unique_ptr <ErrorMessage> em = ErrorMessageFromJSON ( web::json::value::parse ( responseStr ) );
        string expMsg = wstring2string ( em -> msg );
        throw exception ( expMsg . c_str () );
    }

    return NULL;
}

wstring requestQuery ( wchar_t* rawSql, char* serverAddr, long port, char* username,
                                          char* passwd,
                                          char* project,
										  bool isPrepare,
										  int* statusFlag)
{
    //using local cache to intercept probing queries
    const wchar_t* cachedQueryRes = NULL;

	if (isPrepare) {
		cachedQueryRes = loadCache ( rawSql  );
	}

    if ( cachedQueryRes != NULL )
    {
		*statusFlag = 1;
        return cachedQueryRes;
    }

    //real requesting
    wstring serverAddrW = completeServerStr ( serverAddr, port );
    http_client_config config;
    config . set_timeout ( utility::seconds ( 36000 ) );

	//uncomment these lines for debug with proxy
	//wstring p = L"http://127.0.0.1:8888";
	//config.set_proxy(web_proxy(p));

    http_client session ( serverAddrW, config );
    http_request request;

	if (!isPrepare)
	{
		request = makeRequest ( username, passwd, L"/kylin/api/query", methods::POST );
	}

	else
	{
		request = makeRequest ( username, passwd, L"/kylin/api/query/prestate", methods::POST );
	}

    wstring sql = cookQuery ( rawSql );
    std::wstringstream wss;
    wss << L"{ \"acceptPartial\": false, \"project\" : \"" << project << L"\", " << " \"sql\" : \"" << sql << L"\"";

	// backward compatible, Apache Kylin <=2.0
	if (isPrepare)
	{
		wss << L", \"params\" : [] ";
	}

	wss << L"}" ;

    request . set_body ( wss . str (), L"application/json" );
    request . headers () . add ( header_names::accept_encoding, "gzip,deflate" );
    http_response response;
	http::status_code status;

	try
    {
        response = session . request ( request ) . get ();
        status = response . status_code ();
    }

    catch ( std::exception& e )
    {
        std::stringstream ss;
        ss << "An exception is throw Error message: " << e . what ();
        throw exception ( ss . str () . c_str () );
    }

	if ( status == status_codes::OK )
    {
        *statusFlag = 1;
    }

    else if ( status == status_codes::InternalError )
    {
        *statusFlag = 0;
    }

    else
    {
        throw exception ( "Unknown exception in rest query with return code " + status );
    }

	wstring ret = getBodyString ( response );

    if (*statusFlag == 1 && isPrepare)
    {
        storeCache(rawSql, ret.c_str());
    }
	return ret;
}

<|endoftext|>


<commit_before>#include "ofApp.h"

#include "shared2030.h"

#ifdef __MULTI_CLIENT_ENABLED__
    #include "multi_client.hpp"
#endif

#include "interface.hpp"
#include "osc_receiver.hpp"
#include "xml_configs.hpp"
#include "xml_triggers.hpp"
#include "shader_manager.hpp"
#include "xml_settings.hpp"
#include "player.hpp"
#include "renderer.hpp"
#include "interface_player_bridge.hpp"
#include "effect_manager.hpp"
#include "video_manager.hpp"
#include "osc_playback_manager.hpp"
#include "osc_recorder.hpp"

//--------------------------------------------------------------
void ofApp::setup(){
    ofSetLogLevel(OF_LOG_VERBOSE);
    ofLogVerbose() << "Redirect logging to log.txt";
    ofLogToFile("log.txt", true);
    ofLog() << "window size: " << ofGetWidth() << "x" << ofGetHeight();

#ifdef __HIDE_CURSOR__
    ofHideCursor();
#endif

#ifdef __SET_DATA_ROOT_PATH__
    ofSetDataPathRoot("data/");
#endif

    // load settings xml
    ofLogVerbose() << "Loading settings.xml";
    if(!of2030::XmlSettings::instance()->load()){
        ofLogError() << "Could not load settings.xml";
        std::exit(1);
    }

    // apply log-level setting
    ofLogVerbose() << "Set log level based on setting: " << of2030::XmlSettings::instance()->log_level_name;
    ofSetLogLevel(of2030::XmlSettings::instance()->log_level);

    // load effects xml
    ofLogVerbose() << "Loading effects.xml";
    of2030::XmlEffects::instance()->load();

    // load screens xml
    ofLogVerbose() << "Loading screens.xml";

#ifndef __MULTI_CLIENT_ENABLED__
    // our screens.xml loader only needs to load the configuration for our own screen
    of2030::XmlConfigs::screens()->setNameFilter(of2030::XmlSettings::instance()->client_id);
#endif
    of2030::XmlConfigs::screens()->load();

    // load triggers xml
    ofLogVerbose() << "Loading triggers.xml";
    of2030::XmlTriggers::instance()->load();

    // load and start player
    ofLogVerbose() << "Starting player";
    of2030::Player::instance()->start();

    // This bridge updates the player with new effects, songnames and clipnames
    // when events on the interface are triggered
    // it auto-initializes with the interface and player singleton instances
    ofLogVerbose() << "Setting up InterfacePlayerBridge";
    of2030::InterfacePlayerBridge::instance()->setup();

#ifdef __MULTI_CLIENT_ENABLED__
    ofLogVerbose() << "Setting up MultiClient";
    of2030::MultiClient::instance()->setup();

    // only load singleton renderer when not in multi-mode
    if(!of2030::MultiClient::instance()->enabled){
        // Load renderer
        ofLogNotice() << "MultiClient not enabled, setting up singleton renderer";
        of2030::Renderer::instance()->setClientId(of2030::XmlSettings::instance()->client_id);
        of2030::Renderer::instance()->setup();
    }
#else
    ofLogVerbose() << "Setting up Renderer";
    of2030::Renderer::instance()->setClientId(of2030::XmlSettings::instance()->client_id);
    of2030::Renderer::instance()->setup();
#endif

    ofAddListener(of2030::Interface::instance()->controlEvent, this, &ofApp::onControl);
    ofAddListener(of2030::Interface::instance()->playbackEvent, this, &ofApp::onPlayback);
    ofAddListener(of2030::Interface::instance()->stopPlaybackEvent, this, &ofApp::onStopPlayback);
    ofAddListener(of2030::Interface::instance()->loadVideoEvent, this, &ofApp::onLoadVideo);
    ofAddListener(of2030::Interface::instance()->unloadVideoEvent, this, &ofApp::onUnloadVideo);

    // load & start OscReceiver; let the messages come!
    ofLogVerbose() << "Starting OscReceiver";
    of2030::OscReceiver::instance()->configure(of2030::XmlSettings::instance()->osc_setting);
    of2030::OscReceiver::instance()->setup();

    // for debugging; start recorded osc sequence
    // of2030::OscPlaybackManager::instance()->start("_rec");
    // of2030::OscPlaybackManager::instance()->start("clock_spot");

    // using the player's time as main timing mechanism
    next_log_alive_time = of2030::Player::instance()->getTime();
    ofClear(0);
}

//--------------------------------------------------------------
void ofApp::update(){
    of2030::OscPlaybackManager::instance()->update();
    of2030::OscReceiver::instance()->update();
    of2030::Player::instance()->update();
    of2030::VideoManager::instance()->update();

    // time for a new log message to indicate aliveness
    float t = of2030::Player::instance()->getTime();
    if(t >= next_log_alive_time){
        ofLog() << "alive time (s): " << t;
        next_log_alive_time = t + of2030::XmlSettings::instance()->log_alive_interval;
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofBackground(0);

#ifdef __MULTI_CLIENT_ENABLED__
    if(of2030::MultiClient::instance()->enabled){
        of2030::MultiClient::instance()->draw();
    } else {
        of2030::Renderer::instance()->draw();
    }
#else
    of2030::Renderer::instance()->draw();
#endif

#ifdef __OSC_RECORDER_ENABLED__
    if(of2030::OscRecorder::instance()->is_recording()){
        ofSetColor(255, 0, 0);
        ofDrawRectangle(0,0, 10, 10);
    }
#endif
}

//--------------------------------------------------------------
void ofApp::exit(ofEventArgs &args){
    ofLog() << "shutting down...\n";

    // TODO; call delete_instance for all singleton instance implementations
    of2030::EfficientEffectManager::delete_instance();
    of2030::VideoManager::delete_instance();

#ifdef __OSC_RECORDER_ENABLED__
    of2030::OscRecorder::delete_instance();
#endif
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
#ifdef __OSC_RECORDER_ENABLED__
    if(key == 'r'){
        of2030::OscRecorder::instance()->toggle_record();
    }
#endif

#ifdef __MULTI_CLIENT_ENABLED__
    if(key >= '0' && key <= '9'){
        of2030::MultiClient::instance()->setPreviewClient(key-'0');
        return;
    }
    if(key ==45){ // minus/dash
        of2030::MultiClient::instance()->setPreviewClient(-1);
        return;
    }
    if(OF_KEY_LEFT){
        int idx = of2030::MultiClient::instance()->getPreviewClient()-1;
        if(idx < -1){
            idx = of2030::MultiClient::instance()->getClientCount()-1;
        }
        of2030::MultiClient::instance()->setPreviewClient(idx);
        return;
    }
    if(OF_KEY_RIGHT){
        int idx = of2030::MultiClient::instance()->getPreviewClient()+1;
        if(idx >= of2030::MultiClient::instance()->getClientCount()){
            idx=-1;
        }
        of2030::MultiClient::instance()->setPreviewClient(idx);
        return;
    }
#endif
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){
#ifdef __DRAGNDROP__
    for(auto file: dragInfo.files){
        of2030::OscPlaybackManager::instance()->start(file);
    }
#endif // __DRAGNDROP__
}

void ofApp::onControl(string &type){

    if(type == CTRL_RELOAD_SHADERS){
        ofLog() << "reloading shader";
        of2030::Player::instance()->clearEffects();
        of2030::ShaderManager::instance()->clear();
        return;
    }

    if(type == CTRL_RELOAD_EFFECTS){
        ofLog() << "reloading effects";
        of2030::XmlTriggers::instance()->load();
        of2030::XmlConfigs::instance()->load();
        return;
    }

    if(type == CTRL_RELOAD_SCREENS){
        ofLog() << "reloading screens";
        of2030::XmlConfigs::screens()->load();
#ifdef __MULTI_CLIENT_ENABLED__
        of2030::MultiClient::instance()->setup();
#endif
        return;
    }

    if(type == CTRL_RELOAD_SETTINGS){
        ofLog() << "reloading settings";
        of2030::XmlSettings::instance()->load(true);
        ofSetLogLevel(of2030::XmlSettings::instance()->log_level);
        of2030::OscReceiver::instance()->configure(of2030::XmlSettings::instance()->osc_setting);
#ifdef __MULTI_CLIENT_ENABLED__
        of2030::MultiClient::instance()->setup();
#endif
        return;
    }

    if(type == CTRL_RELOAD_CLIENTS){
        ofLogWarning() << "reload clients is deprecated";
        // of2030::XmlClients::instance()->load();
        return;
    }
}

void ofApp::onPlayback(string &name){
    of2030::OscPlaybackManager::instance()->start(name);
}

void ofApp::onStopPlayback(string &name){
    of2030::OscPlaybackManager::instance()->stop(name);
}

void ofApp::onLoadVideo(string &name){
    of2030::VideoManager::instance()->get(name, true);
}

void ofApp::onUnloadVideo(string &name){
    if(name == ""){ // unload all?
        of2030::Player::instance()->stopAllVideoEffects();
    } else {
        ofVideoPlayer* player = of2030::VideoManager::instance()->get(name, false);
        // could be NULL!
        of2030::Player::instance()->stopEffectsByVideoPlayer(player);
    }

    of2030::VideoManager::instance()->unload(name);
}
<commit_msg>key down typo bif<commit_after>#include "ofApp.h"

#include "shared2030.h"

#ifdef __MULTI_CLIENT_ENABLED__
    #include "multi_client.hpp"
#endif

#include "interface.hpp"
#include "osc_receiver.hpp"
#include "xml_configs.hpp"
#include "xml_triggers.hpp"
#include "shader_manager.hpp"
#include "xml_settings.hpp"
#include "player.hpp"
#include "renderer.hpp"
#include "interface_player_bridge.hpp"
#include "effect_manager.hpp"
#include "video_manager.hpp"
#include "osc_playback_manager.hpp"
#include "osc_recorder.hpp"

//--------------------------------------------------------------
void ofApp::setup(){
    ofSetLogLevel(OF_LOG_VERBOSE);
    ofLogVerbose() << "Redirect logging to log.txt";
    ofLogToFile("log.txt", true);
    ofLog() << "window size: " << ofGetWidth() << "x" << ofGetHeight();

#ifdef __HIDE_CURSOR__
    ofHideCursor();
#endif

#ifdef __SET_DATA_ROOT_PATH__
    ofSetDataPathRoot("data/");
#endif

    // load settings xml
    ofLogVerbose() << "Loading settings.xml";
    if(!of2030::XmlSettings::instance()->load()){
        ofLogError() << "Could not load settings.xml";
        std::exit(1);
    }

    // apply log-level setting
    ofLogVerbose() << "Set log level based on setting: " << of2030::XmlSettings::instance()->log_level_name;
    ofSetLogLevel(of2030::XmlSettings::instance()->log_level);

    // load effects xml
    ofLogVerbose() << "Loading effects.xml";
    of2030::XmlEffects::instance()->load();

    // load screens xml
    ofLogVerbose() << "Loading screens.xml";

#ifndef __MULTI_CLIENT_ENABLED__
    // our screens.xml loader only needs to load the configuration for our own screen
    of2030::XmlConfigs::screens()->setNameFilter(of2030::XmlSettings::instance()->client_id);
#endif
    of2030::XmlConfigs::screens()->load();

    // load triggers xml
    ofLogVerbose() << "Loading triggers.xml";
    of2030::XmlTriggers::instance()->load();

    // load and start player
    ofLogVerbose() << "Starting player";
    of2030::Player::instance()->start();

    // This bridge updates the player with new effects, songnames and clipnames
    // when events on the interface are triggered
    // it auto-initializes with the interface and player singleton instances
    ofLogVerbose() << "Setting up InterfacePlayerBridge";
    of2030::InterfacePlayerBridge::instance()->setup();

#ifdef __MULTI_CLIENT_ENABLED__
    ofLogVerbose() << "Setting up MultiClient";
    of2030::MultiClient::instance()->setup();

    // only load singleton renderer when not in multi-mode
    if(!of2030::MultiClient::instance()->enabled){
        // Load renderer
        ofLogNotice() << "MultiClient not enabled, setting up singleton renderer";
        of2030::Renderer::instance()->setClientId(of2030::XmlSettings::instance()->client_id);
        of2030::Renderer::instance()->setup();
    }
#else
    ofLogVerbose() << "Setting up Renderer";
    of2030::Renderer::instance()->setClientId(of2030::XmlSettings::instance()->client_id);
    of2030::Renderer::instance()->setup();
#endif

    ofAddListener(of2030::Interface::instance()->controlEvent, this, &ofApp::onControl);
    ofAddListener(of2030::Interface::instance()->playbackEvent, this, &ofApp::onPlayback);
    ofAddListener(of2030::Interface::instance()->stopPlaybackEvent, this, &ofApp::onStopPlayback);
    ofAddListener(of2030::Interface::instance()->loadVideoEvent, this, &ofApp::onLoadVideo);
    ofAddListener(of2030::Interface::instance()->unloadVideoEvent, this, &ofApp::onUnloadVideo);

    // load & start OscReceiver; let the messages come!
    ofLogVerbose() << "Starting OscReceiver";
    of2030::OscReceiver::instance()->configure(of2030::XmlSettings::instance()->osc_setting);
    of2030::OscReceiver::instance()->setup();

    // for debugging; start recorded osc sequence
    // of2030::OscPlaybackManager::instance()->start("_rec");
    // of2030::OscPlaybackManager::instance()->start("clock_spot");

    // using the player's time as main timing mechanism
    next_log_alive_time = of2030::Player::instance()->getTime();
    ofClear(0);
}

//--------------------------------------------------------------
void ofApp::update(){
    of2030::OscPlaybackManager::instance()->update();
    of2030::OscReceiver::instance()->update();
    of2030::Player::instance()->update();
    of2030::VideoManager::instance()->update();

    // time for a new log message to indicate aliveness
    float t = of2030::Player::instance()->getTime();
    if(t >= next_log_alive_time){
        ofLog() << "alive time (s): " << t;
        next_log_alive_time = t + of2030::XmlSettings::instance()->log_alive_interval;
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofBackground(0);

#ifdef __MULTI_CLIENT_ENABLED__
    if(of2030::MultiClient::instance()->enabled){
        of2030::MultiClient::instance()->draw();
    } else {
        of2030::Renderer::instance()->draw();
    }
#else
    of2030::Renderer::instance()->draw();
#endif

#ifdef __OSC_RECORDER_ENABLED__
    if(of2030::OscRecorder::instance()->is_recording()){
        ofSetColor(255, 0, 0);
        ofDrawRectangle(0,0, 10, 10);
    }
#endif
}

//--------------------------------------------------------------
void ofApp::exit(ofEventArgs &args){
    ofLog() << "shutting down...\n";

    // TODO; call delete_instance for all singleton instance implementations
    of2030::EfficientEffectManager::delete_instance();
    of2030::VideoManager::delete_instance();

#ifdef __OSC_RECORDER_ENABLED__
    of2030::OscRecorder::delete_instance();
#endif
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
#ifdef __OSC_RECORDER_ENABLED__
    if(key == 'r'){
        of2030::OscRecorder::instance()->toggle_record();
    }
#endif

#ifdef __MULTI_CLIENT_ENABLED__
    if(key >= '0' && key <= '9'){
        of2030::MultiClient::instance()->setPreviewClient(key-'0');
        return;
    }
    if(key ==45){ // minus/dash
        of2030::MultiClient::instance()->setPreviewClient(-1);
        return;
    }
    if(key == OF_KEY_LEFT){
        int idx = of2030::MultiClient::instance()->getPreviewClient()-1;
        if(idx < -1){
            idx = of2030::MultiClient::instance()->getClientCount()-1;
        }
        of2030::MultiClient::instance()->setPreviewClient(idx);
        return;
    }
    if(key == OF_KEY_RIGHT){
        int idx = of2030::MultiClient::instance()->getPreviewClient()+1;
        if(idx >= of2030::MultiClient::instance()->getClientCount()){
            idx=-1;
        }
        of2030::MultiClient::instance()->setPreviewClient(idx);
        return;
    }
#endif
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){
#ifdef __DRAGNDROP__
    for(auto file: dragInfo.files){
        of2030::OscPlaybackManager::instance()->start(file);
    }
#endif // __DRAGNDROP__
}

void ofApp::onControl(string &type){

    if(type == CTRL_RELOAD_SHADERS){
        ofLog() << "reloading shader";
        of2030::Player::instance()->clearEffects();
        of2030::ShaderManager::instance()->clear();
        return;
    }

    if(type == CTRL_RELOAD_EFFECTS){
        ofLog() << "reloading effects";
        of2030::XmlTriggers::instance()->load();
        of2030::XmlConfigs::instance()->load();
        return;
    }

    if(type == CTRL_RELOAD_SCREENS){
        ofLog() << "reloading screens";
        of2030::XmlConfigs::screens()->load();
#ifdef __MULTI_CLIENT_ENABLED__
        of2030::MultiClient::instance()->setup();
#endif
        return;
    }

    if(type == CTRL_RELOAD_SETTINGS){
        ofLog() << "reloading settings";
        of2030::XmlSettings::instance()->load(true);
        ofSetLogLevel(of2030::XmlSettings::instance()->log_level);
        of2030::OscReceiver::instance()->configure(of2030::XmlSettings::instance()->osc_setting);
#ifdef __MULTI_CLIENT_ENABLED__
        of2030::MultiClient::instance()->setup();
#endif
        return;
    }

    if(type == CTRL_RELOAD_CLIENTS){
        ofLogWarning() << "reload clients is deprecated";
        // of2030::XmlClients::instance()->load();
        return;
    }
}

void ofApp::onPlayback(string &name){
    of2030::OscPlaybackManager::instance()->start(name);
}

void ofApp::onStopPlayback(string &name){
    of2030::OscPlaybackManager::instance()->stop(name);
}

void ofApp::onLoadVideo(string &name){
    of2030::VideoManager::instance()->get(name, true);
}

void ofApp::onUnloadVideo(string &name){
    if(name == ""){ // unload all?
        of2030::Player::instance()->stopAllVideoEffects();
    } else {
        ofVideoPlayer* player = of2030::VideoManager::instance()->get(name, false);
        // could be NULL!
        of2030::Player::instance()->stopEffectsByVideoPlayer(player);
    }

    of2030::VideoManager::instance()->unload(name);
}
<|endoftext|>


<commit_before>// Copyright (c) 2012-2013 Plenluno All rights reserved.

#include <gtest/gtest.h>
#include <libnode/trace.h>
#include <libnode/debug_print.h>
#include <libnode/detail/http/agent.h>

#include <libj/detail/gc_collect.h>

#include "./gtest_common.h"

int main(int argc, char** argv) {
    LIBNODE_DEBUG_TRACE_ON;

    testing::InitGoogleTest(&argc, argv);
    int r = RUN_ALL_TESTS();

    libj::node::GTestOnEnd::clear();
    libj::node::detail::http::freeGlobalAgent();

    LIBJ_GC_COLLECT;

    LIBJ_DEBUG_PRINT(
        "remaining objects: %d",
        LIBJ_DEBUG_OBJECT_COUNT);

    LIBNODE_DEBUG_TRACE_OFF;
    return r;
}
<commit_msg>add '#ifdef LIBNODE_DEBUG'<commit_after>// Copyright (c) 2012-2013 Plenluno All rights reserved.

#include <gtest/gtest.h>
#include <libnode/trace.h>
#include <libnode/debug_print.h>
#include <libnode/detail/http/agent.h>

#include <libj/detail/gc_collect.h>

#include "./gtest_common.h"

int main(int argc, char** argv) {
    LIBNODE_DEBUG_TRACE_ON;

    testing::InitGoogleTest(&argc, argv);
    int r = RUN_ALL_TESTS();

#ifdef LIBNODE_DEBUG
    libj::node::GTestOnEnd::clear();
    libj::node::detail::http::freeGlobalAgent();
#endif

    LIBJ_GC_COLLECT;

    LIBJ_DEBUG_PRINT(
        "remaining objects: %d",
        LIBJ_DEBUG_OBJECT_COUNT);

    LIBNODE_DEBUG_TRACE_OFF;
    return r;
}
<|endoftext|>


<commit_before>// Copyright 2021 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

// clang-format off
#include "pw_rpc/internal/log_config.h"  // PW_LOG_* macros must be first.

#include "pw_rpc/internal/endpoint.h"
// clang-format on

#include "pw_log/log.h"
#include "pw_rpc/internal/lock.h"

namespace pw::rpc::internal {

RpcLock& rpc_lock() {
  static RpcLock lock;
  return lock;
}

Endpoint::~Endpoint() {
  // Since the calls remove themselves from the Endpoint in
  // CloseAndSendResponse(), close responders until no responders remain.
  while (!calls_.empty()) {
    calls_.front().CloseAndSendResponse(OkStatus()).IgnoreError();
  }
}

Result<Packet> Endpoint::ProcessPacket(std::span<const std::byte> data,
                                       Packet::Destination destination) {
  Result<Packet> result = Packet::FromBuffer(data);

  if (!result.ok()) {
    PW_LOG_WARN("Failed to decode pw_rpc packet");
    return Status::DataLoss();
  }

  Packet& packet = *result;

  if (packet.channel_id() == Channel::kUnassignedChannelId ||
      packet.service_id() == 0 || packet.method_id() == 0) {
    PW_LOG_WARN("Received malformed pw_rpc packet");
    return Status::DataLoss();
  }

  if (packet.destination() != destination) {
    return Status::InvalidArgument();
  }

  return result;
}

void Endpoint::RegisterCall(Call& call) {
  LockGuard lock(rpc_lock());

  Call* const existing_call = FindCallById(
      call.channel_id_locked(), call.service_id(), call.method_id());

  RegisterUniqueCall(call);

  if (existing_call != nullptr) {
    existing_call->ReplaceWithNewInstance(call);
  } else {
    rpc_lock().unlock();
  }
}

Channel* Endpoint::GetInternalChannel(uint32_t id) const {
  for (Channel& c : channels_) {
    if (c.id() == id) {
      return &c;
    }
  }
  return nullptr;
}

Channel* Endpoint::AssignChannel(uint32_t id, ChannelOutput& interface) {
  internal::Channel* channel =
      GetInternalChannel(Channel::kUnassignedChannelId);
  if (channel == nullptr) {
    return nullptr;
  }

  *channel = Channel(id, &interface);
  return channel;
}

Call* Endpoint::FindCallById(uint32_t channel_id,
                             uint32_t service_id,
                             uint32_t method_id) {
  for (Call& call : calls_) {
    if (channel_id == call.channel_id_locked() &&
        service_id == call.service_id() && method_id == call.method_id()) {
      return &call;
    }
  }
  return nullptr;
}

}  // namespace pw::rpc::internal
<commit_msg>pw_rpc: Fix double mutex unlock<commit_after>// Copyright 2021 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

// clang-format off
#include "pw_rpc/internal/log_config.h"  // PW_LOG_* macros must be first.

#include "pw_rpc/internal/endpoint.h"
// clang-format on

#include "pw_log/log.h"
#include "pw_rpc/internal/lock.h"

namespace pw::rpc::internal {

RpcLock& rpc_lock() {
  static RpcLock lock;
  return lock;
}

Endpoint::~Endpoint() {
  // Since the calls remove themselves from the Endpoint in
  // CloseAndSendResponse(), close responders until no responders remain.
  while (!calls_.empty()) {
    calls_.front().CloseAndSendResponse(OkStatus()).IgnoreError();
  }
}

Result<Packet> Endpoint::ProcessPacket(std::span<const std::byte> data,
                                       Packet::Destination destination) {
  Result<Packet> result = Packet::FromBuffer(data);

  if (!result.ok()) {
    PW_LOG_WARN("Failed to decode pw_rpc packet");
    return Status::DataLoss();
  }

  Packet& packet = *result;

  if (packet.channel_id() == Channel::kUnassignedChannelId ||
      packet.service_id() == 0 || packet.method_id() == 0) {
    PW_LOG_WARN("Received malformed pw_rpc packet");
    return Status::DataLoss();
  }

  if (packet.destination() != destination) {
    return Status::InvalidArgument();
  }

  return result;
}

void Endpoint::RegisterCall(Call& call) {
  rpc_lock().lock();

  Call* const existing_call = FindCallById(
      call.channel_id_locked(), call.service_id(), call.method_id());

  RegisterUniqueCall(call);

  if (existing_call != nullptr) {
    existing_call->ReplaceWithNewInstance(call);
  } else {
    rpc_lock().unlock();
  }
}

Channel* Endpoint::GetInternalChannel(uint32_t id) const {
  for (Channel& c : channels_) {
    if (c.id() == id) {
      return &c;
    }
  }
  return nullptr;
}

Channel* Endpoint::AssignChannel(uint32_t id, ChannelOutput& interface) {
  internal::Channel* channel =
      GetInternalChannel(Channel::kUnassignedChannelId);
  if (channel == nullptr) {
    return nullptr;
  }

  *channel = Channel(id, &interface);
  return channel;
}

Call* Endpoint::FindCallById(uint32_t channel_id,
                             uint32_t service_id,
                             uint32_t method_id) {
  for (Call& call : calls_) {
    if (channel_id == call.channel_id_locked() &&
        service_id == call.service_id() && method_id == call.method_id()) {
      return &call;
    }
  }
  return nullptr;
}

}  // namespace pw::rpc::internal
<|endoftext|>