You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
workflow/WFConsulClient.cc

1478 lines
39 KiB

/*
Copyright (c) 2022 Sogou, Inc.
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
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.
Authors: Wang Zhenpeng (wangzhenpeng@sogou-inc.com)
*/
#include <string.h>
#include <string>
#include <vector>
#include <utility>
#include <functional>
#include "json_parser.h" // JSON<4F><4E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#include "StringUtil.h" // <20>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#include "URIParser.h" // URI<52><49><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#include "HttpUtil.h" // HTTP<54><50><EFBFBD>ع<EFBFBD><D8B9><EFBFBD>
#include "WFConsulClient.h" // Consul<75>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ض<EFBFBD><D8B6><EFBFBD>
using namespace protocol; // ʹ<><CAB9>Э<EFBFBD><D0AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>
// WFConsulTask <20><><EFBFBD><EFBFBD><ECBAAF>
WFConsulTask::WFConsulTask(const std::string& proxy_url,
const std::string& service_namespace,
const std::string& service_name,
const std::string& service_id,
int retry_max,
consul_callback_t&& cb) :
proxy_url(proxy_url), // <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
callback(std::move(cb)) // <20><><EFBFBD>ûص<C3BB><D8B5><EFBFBD><EFBFBD><EFBFBD>
{
this->service.service_name = service_name; // <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
this->service.service_namespace = service_namespace; // <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>
this->service.service_id = service_id; // <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ID
this->api_type = CONSUL_API_TYPE_UNKNOWN; // <20><><EFBFBD><EFBFBD> API <20><><EFBFBD><EFBFBD>Ϊδ֪
this->retry_max = retry_max; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD>
this->finish = false; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD><EFBFBD>
this->consul_index = 0; // <20><>ʼ<EFBFBD><CABC> Consul <20><><EFBFBD><EFBFBD>Ϊ 0
}
// <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
void WFConsulTask::set_service(const struct protocol::ConsulService *service)
{
this->service.tags = service->tags; // <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD>ǩ
this->service.meta = service->meta; // <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD>Ԫ<EFBFBD><D4AA>Ϣ
this->service.tag_override = service->tag_override; // <20><><EFBFBD>ñ<EFBFBD>ǩ<EFBFBD><C7A9><EFBFBD>DZ<EFBFBD>־
this->service.service_address = service->service_address; // <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD>ַ
this->service.lan = service->lan; // <20><><EFBFBD>ñ<EFBFBD><C3B1>ؾ<EFBFBD><D8BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
this->service.lan_ipv4 = service->lan_ipv4; // <20><><EFBFBD><EFBFBD> IPv4 <20><>ַ
this->service.lan_ipv6 = service->lan_ipv6; // <20><><EFBFBD><EFBFBD> IPv6 <20><>ַ
this->service.virtual_address = service->virtual_address; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
this->service.wan = service->wan; // <20><><EFBFBD>ù<EFBFBD><C3B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
this->service.wan_ipv4 = service->wan_ipv4; // <20><><EFBFBD><EFBFBD> IPv4 <20><>ַ
this->service.wan_ipv6 = service->wan_ipv6; // <20><><EFBFBD><EFBFBD> IPv6 <20><>ַ
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD><EFBFBD>ľ<EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD>
static bool parse_discover_result(const json_value_t *root,
std::vector<struct ConsulServiceInstance>& result);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ľ<EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD>
static bool parse_list_service_result(const json_value_t *root,
std::vector<struct ConsulServiceTags>& result);
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>
bool WFConsulTask::get_discover_result(
std::vector<struct ConsulServiceInstance>& result)
{
json_value_t *root; // JSON <20><><EFBFBD>ڵ<EFBFBD>
int errno_bak; // <20><><EFBFBD>ݵ<EFBFBD>ǰ errno ֵ
bool ret; // <20><><EFBFBD>ؽ<EFBFBD><D8BD><EFBFBD><EFBFBD><EFBFBD>־
// <20><><EFBFBD>鵱ǰ API <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (this->api_type != CONSUL_API_TYPE_DISCOVER)
{
errno = EPERM; // <20><><EFBFBD><EFBFBD>Ȩ<EFBFBD>޴<EFBFBD><DEB4><EFBFBD>
return false; // <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
}
errno_bak = errno; // <20><><EFBFBD><EFBFBD> errno
errno = EBADMSG; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>
std::string body = HttpUtil::decode_chunked_body(&this->http_resp); // <20><><EFBFBD><EFBFBD> HTTP <20><>Ӧ<EFBFBD>ķֿ<C4B7><D6BF><EFBFBD><EFBFBD><EFBFBD>
root = json_value_parse(body.c_str()); // <20><><EFBFBD><EFBFBD> JSON <20><><EFBFBD><EFBFBD>
if (!root) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
return false; // <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
ret = parse_discover_result(root, result); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>
json_value_destroy(root); // <20><><EFBFBD><EFBFBD> JSON <20><><EFBFBD><EFBFBD>
if (ret) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>
errno = errno_bak; // <20>ָ<EFBFBD>ԭʼ errno
return ret; // <20><><EFBFBD>ؽ<EFBFBD><D8BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>
bool WFConsulTask::get_list_service_result(
std::vector<struct ConsulServiceTags>& result)
{
json_value_t *root; // JSON <20><><EFBFBD>ڵ<EFBFBD>
int errno_bak; // <20><><EFBFBD>ݵ<EFBFBD>ǰ errno ֵ
bool ret; // <20><><EFBFBD>ؽ<EFBFBD><D8BD><EFBFBD><EFBFBD><EFBFBD>־
// <20><><EFBFBD>鵱ǰ API <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
if (this->api_type != CONSUL_API_TYPE_LIST_SERVICE)
{
errno = EPERM; // <20><><EFBFBD><EFBFBD>Ȩ<EFBFBD>޴<EFBFBD><DEB4><EFBFBD>
return false; // <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
}
errno_bak = errno; // <20><><EFBFBD><EFBFBD> errno
errno = EBADMSG; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD>
std::string body = HttpUtil::decode_chunked_body(&this->http_resp); // <20><><EFBFBD><EFBFBD> HTTP <20><>Ӧ<EFBFBD>ķֿ<C4B7><D6BF><EFBFBD><EFBFBD><EFBFBD>
root = json_value_parse(body.c_str()); // <20><><EFBFBD><EFBFBD> JSON <20><><EFBFBD><EFBFBD>
if (!root) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
return false; // <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
ret = parse_list_service_result(root, result); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>
json_value_destroy(root); // <20><><EFBFBD><EFBFBD> JSON <20><><EFBFBD><EFBFBD>
if (ret) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>
errno = errno_bak; // <20>ָ<EFBFBD>ԭʼ errno
return ret; // <20><><EFBFBD>ؽ<EFBFBD><D8BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>񣬸<EFBFBD><F1A3ACB8><EFBFBD> API <20><><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߼<EFBFBD>
void WFConsulTask::dispatch()
{
WFHttpTask *task; // <20><><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
if (this->finish) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
this->subtask_done(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return; // <20>˳<EFBFBD>
}
// <20><><EFBFBD><EFBFBD> API <20><><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
switch(this->api_type)
{
case CONSUL_API_TYPE_DISCOVER: // <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
task = create_discover_task(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
break;
case CONSUL_API_TYPE_LIST_SERVICE: // <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>
task = create_list_service_task(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>
break;
case CONSUL_API_TYPE_DEREGISTER: // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
task = create_deregister_task(); // <20><><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
break;
case CONSUL_API_TYPE_REGISTER: // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
task = create_register_task(); // <20><><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (task)
break;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>񴴽<EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD>״̬
if (1)
{
this->state = WFT_STATE_SYS_ERROR; // <20><><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD><EFBFBD>״̬
this->error = errno; // <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD>
}
else
{
default:
this->state = WFT_STATE_TASK_ERROR; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬
this->error = WFT_ERR_CONSUL_API_UNKNOWN; // <20><><EFBFBD><EFBFBD>δ֪ API <20><><EFBFBD><EFBFBD>
}
this->finish = true; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
this->subtask_done(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBB5BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
series_of(this)->push_front(this); // <20><><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
series_of(this)->push_front(task); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
this->subtask_done(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɣ<EFBFBD><C9A3><EFBFBD>ִ<EFBFBD>лص<D0BB><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߼<EFBFBD>
SubTask *WFConsulTask::done()
{
SeriesWork *series = series_of(this); // <20><>ȡ<EFBFBD><C8A1>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>Ĺ<EFBFBD><C4B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (finish) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
if (this->callback) // <20><><EFBFBD><EFBFBD><EFBFBD>лص<D0BB><D8B5><EFBFBD><EFBFBD><EFBFBD>
this->callback(this); // ִ<>лص<D0BB><D8B5><EFBFBD><EFBFBD><EFBFBD>
delete this; // ɾ<><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
return series->pop(); // <20>Ӷ<EFBFBD><D3B6><EFBFBD><EFBFBD>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>ת<EFBFBD><D7AA>Ϊ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD> "5s" <20><> "3m"<22><>
static std::string convert_time_to_str(int milliseconds)
{
std::string str_time; // <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
int seconds = milliseconds / 1000; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>Ϊ<EFBFBD><CEAA>
if (seconds >= 180) // <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><EFBFBD><E4B3AC> 3 <20><><EFBFBD><EFBFBD>
str_time = std::to_string(seconds / 60) + "m"; // ת<><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ
else
str_time = std::to_string(seconds) + "s"; // ת<><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>ʽ
return str_time; // <20><><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
}
// <20><><EFBFBD>ɷ<EFBFBD><C9B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> URL
std::string WFConsulTask::generate_discover_request()
{
std::string url = this->proxy_url; // <20><>ʼ<EFBFBD><CABC> URL Ϊ<><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
// <20><><EFBFBD>ӷ<EFBFBD><D3B7>񽡿<EFBFBD><F1BDA1BF><EFBFBD><EFBFBD><EFBFBD>·<EFBFBD><C2B7>
url += "/v1/health/service/" + this->service.service_name;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>
url += "?dc=" + this->config.get_datacenter();
// <20><><EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>
url += "&ns=" + this->service.service_namespace;
// <20><>ȡ passing <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>ʾ<EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>ʵ<EFBFBD><CAB5>
std::string passing = this->config.get_passing() ? "true" : "false";
url += "&passing=" + passing; // <20><><EFBFBD><EFBFBD> passing <20><><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> token <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD>Ȩ
url += "&token=" + this->config.get_token();
// <20><><EFBFBD>ӹ<EFBFBD><D3B9>˱<EFBFBD><CBB1><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD>
url += "&filter=" + this->config.get_filter_expr();
// <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD> Consul <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ
if (this->config.blocking_query())
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD>ij<EFBFBD>ʼ״̬
url += "&index=" + std::to_string(this->get_consul_index());
// <20><><EFBFBD>ӵȴ<D3B5>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD>ij<EFBFBD>ʱʱ<CAB1><CAB1>
url += "&wait=" + convert_time_to_str(this->config.get_wait_ttl());
}
return url; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD> URL
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
WFHttpTask *WFConsulTask::create_discover_task()
{
std::string url = generate_discover_request(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɷ<EFBFBD><C9B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> URL <20>ĺ<EFBFBD><C4BA><EFBFBD>
WFHttpTask *task = WFTaskFactory::create_http_task( // <20><><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD>
url, 0, this->retry_max, discover_callback);
HttpRequest *req = task->get_req(); // <20><>ȡ HTTP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ JSON
req->add_header_pair("Content-Type", "application/json");
task->user_data = this; // <20><><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return task; // <20><><EFBFBD>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>
WFHttpTask *WFConsulTask::create_list_service_task()
{
std::string url = this->proxy_url; // <20><>ʼ<EFBFBD><CABC> URL Ϊ<><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
// <20><><EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>Ŀ¼·<C2BC><C2B7><EFBFBD>ͼ<EFBFBD>Ȩ token
url += "/v1/catalog/services?token=" + this->config.get_token();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD><C4B2><EFBFBD>
url += "&dc=" + this->config.get_datacenter();
// <20><><EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>
url += "&ns=" + this->service.service_namespace;
WFHttpTask *task = WFTaskFactory::create_http_task( // <20><><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD>
url, 0, this->retry_max, list_service_callback);
HttpRequest *req = task->get_req(); // <20><>ȡ HTTP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ JSON
req->add_header_pair("Content-Type", "application/json");
task->user_data = this; // <20><><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return task; // <20><><EFBFBD>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
static void print_json_value(const json_value_t *val, int depth,
std::string& json_str);
static bool create_register_request(const json_value_t *root,
const struct ConsulService *service,
const ConsulConfig& config);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
WFHttpTask *WFConsulTask::create_register_task()
{
std::string payload; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ洢<DAB4><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
std::string url = this->proxy_url; // <20><>ʼ<EFBFBD><CABC> URL Ϊ<><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
// <20><><EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>ע<EFBFBD><D7A2>·<EFBFBD><C2B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E6BBBB><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
url += "/v1/agent/service/register?replace-existing-checks=";
url += this->config.get_replace_checks() ? "true" : "false";
WFHttpTask *task = WFTaskFactory::create_http_task( // <20><><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD>
url, 0, this->retry_max, register_callback);
HttpRequest *req = task->get_req(); // <20><>ȡ HTTP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
req->set_method(HttpMethodPut); // <20><><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD>Ϊ PUT
req->add_header_pair("Content-Type", "application/json"); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD>Ȩ token<65><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD>ͷ
if (!this->config.get_token().empty())
req->add_header_pair("X-Consul-Token", this->config.get_token());
json_value_t *root = json_value_create(JSON_VALUE_OBJECT); // <20><><EFBFBD><EFBFBD> JSON <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>
if (root) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD> JSON <20><><EFBFBD><EFBFBD>
if (create_register_request(root, &this->service, this->config))
print_json_value(root, 0, payload); // <20><> JSON <20><><EFBFBD><EFBFBD>תΪ<D7AA>ַ<EFBFBD><D6B7><EFBFBD>
json_value_destroy(root); // <20><><EFBFBD><EFBFBD> JSON <20><><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>岻Ϊ<E5B2BB><CEAA><EFBFBD><EFBFBD>׷<EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>
if (!payload.empty() && req->append_output_body(payload))
{
task->user_data = this; // <20><><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return task; // <20><><EFBFBD>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
}
task->dismiss(); // <20><><EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return NULL; // <20><><EFBFBD>ؿ<EFBFBD>ָ<EFBFBD><D6B8>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
WFHttpTask *WFConsulTask::create_deregister_task()
{
std::string url = this->proxy_url; // <20><>ʼ<EFBFBD><CABC> URL Ϊ<><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
// <20><><EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>ע<EFBFBD><D7A2>·<EFBFBD><C2B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ID <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC><EFBFBD><EFBFBD><EFBFBD>
url += "/v1/agent/service/deregister/" + this->service.service_id;
url += "?ns=" + this->service.service_namespace;
WFHttpTask *task = WFTaskFactory::create_http_task( // <20><><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD>
url, 0, this->retry_max, register_callback);
HttpRequest *req = task->get_req(); // <20><>ȡ HTTP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
req->set_method(HttpMethodPut); // <20><><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD>Ϊ PUT
req->add_header_pair("Content-Type", "application/json"); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڼ<EFBFBD>Ȩ token<65><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD>ͷ
std::string token = this->config.get_token();
if (!token.empty())
req->add_header_pair("X-Consul-Token", token);
task->user_data = this; // <20><><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return task; // <20><><EFBFBD>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>н<EFBFBD><D0BD><EFBFBD>
bool WFConsulTask::check_task_result(WFHttpTask *task, WFConsulTask *consul_task)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬<D7B4><CCAC><EFBFBD>dzɹ<C7B3>״̬
if (task->get_state() != WFT_STATE_SUCCESS)
{
consul_task->state = task->get_state(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬
consul_task->error = task->get_error(); // <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD>Ϣ
return false; // <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HTTP <20><>Ӧ
protocol::HttpResponse *resp = task->get_resp();
// <20><><EFBFBD><EFBFBD> HTTP <20><>Ӧ״̬<D7B4><CCAC><EFBFBD>Ƿ<EFBFBD>Ϊ "200"
if (strcmp(resp->get_status_code(), "200") != 0)
{
consul_task->state = WFT_STATE_TASK_ERROR; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬
consul_task->error = WFT_ERR_CONSUL_CHECK_RESPONSE_FAILED; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧʧ<D3A6>ܴ<EFBFBD><DCB4><EFBFBD>
return false; // <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
}
return true; // <20><><EFBFBD>سɹ<D8B3>
}
// <20><> HTTP <20><>Ӧͷ<D3A6>л<EFBFBD>ȡ Consul <20><><EFBFBD><EFBFBD>
long long WFConsulTask::get_consul_index(HttpResponse *resp)
{
long long consul_index = 0; // <20><>ʼ<EFBFBD><CABC> Consul <20><><EFBFBD><EFBFBD>Ϊ 0
// <20><><EFBFBD><EFBFBD> HTTP ͷ<>α<EFBFBD><CEB1>Ա<EFBFBD><D4B1><EFBFBD><EFBFBD><EFBFBD>Ӧͷ
protocol::HttpHeaderCursor cursor(resp);
std::string consul_index_str; // <20><><EFBFBD>ڴ洢 Consul <20><><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
// <20><><EFBFBD><EFBFBD> "X-Consul-Index" <20><>Ӧͷ
if (cursor.find("X-Consul-Index", consul_index_str))
{
// <20><><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>ת<EFBFBD><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
consul_index = strtoll(consul_index_str.c_str(), NULL, 10);
if (consul_index < 0) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1> 0<><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 0
consul_index = 0;
}
return consul_index; // <20><><EFBFBD><EFBFBD> Consul <20><><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD>
void WFConsulTask::discover_callback(WFHttpTask *task)
{
WFConsulTask *t = (WFConsulTask*)task->user_data; // <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>н<EFBFBD><D0BD><EFBFBD>
if (WFConsulTask::check_task_result(task, t))
{
protocol::HttpResponse *resp = task->get_resp(); // <20><>ȡ HTTP <20><>Ӧ
long long consul_index = t->get_consul_index(resp); // <20><>ȡ<EFBFBD><C8A1>ǰ Consul <20><><EFBFBD><EFBFBD>
long long last_consul_index = t->get_consul_index(); // <20><>ȡ<EFBFBD><C8A1>һ<EFBFBD>ε<EFBFBD> Consul <20><><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> Consul <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ 0
t->set_consul_index(consul_index < last_consul_index ? 0 : consul_index);
t->state = task->get_state(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬
}
// <20><> HTTP <20><>Ӧת<D3A6>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
t->http_resp = std::move(*task->get_resp());
t->finish = true; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD>
void WFConsulTask::list_service_callback(WFHttpTask *task)
{
WFConsulTask *t = (WFConsulTask*)task->user_data; // <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>н<EFBFBD><D0BD><EFBFBD>
if (WFConsulTask::check_task_result(task, t))
t->state = task->get_state(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬
// <20><> HTTP <20><>Ӧת<D3A6>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
t->http_resp = std::move(*task->get_resp());
t->finish = true; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ļص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD>
void WFConsulTask::register_callback(WFHttpTask *task)
{
WFConsulTask *t = (WFConsulTask *)task->user_data; // <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>н<EFBFBD><D0BD><EFBFBD>
if (WFConsulTask::check_task_result(task, t))
t->state = task->get_state(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬
// <20><> HTTP <20><>Ӧת<D3A6>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
t->http_resp = std::move(*task->get_resp());
t->finish = true; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><>ʼ<EFBFBD><CABC> Consul <20>ͻ<EFBFBD><CDBB><EFBFBD>
int WFConsulClient::init(const std::string& proxy_url, ConsulConfig config)
{
ParsedURI uri; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ洢<DAB4><E6B4A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> URI <20>Ķ<EFBFBD><C4B6><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> URL
if (URIParser::parse(proxy_url, uri) >= 0)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD> URL
this->proxy_url = uri.scheme;
this->proxy_url += "://";
this->proxy_url += uri.host;
if (uri.port) // <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD>˶˿ڣ<CBBF><DAA3><EFBFBD>׷<EFBFBD>Ӷ˿<D3B6><CBBF><EFBFBD>Ϣ
{
this->proxy_url += ":";
this->proxy_url += uri.port;
}
this->config = std::move(config); // <20><><EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD>
return 0; // <20><><EFBFBD>سɹ<D8B3>
}
else if (uri.state == URI_STATE_INVALID) // <20><><EFBFBD><EFBFBD> URI <20><>Ч
errno = EINVAL; // <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD>
return -1; // <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
}
// <20><>ʼ<EFBFBD><CABC> Consul <20>ͻ<EFBFBD><CDBB>ˣ<EFBFBD>ʹ<EFBFBD><CAB9>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD>
int WFConsulClient::init(const std::string& proxy_url)
{
return this->init(proxy_url, ConsulConfig()); // <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD>ò<EFBFBD><C3B2><EFBFBD><EFBFBD><EFBFBD> init <20><><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
WFConsulTask *WFConsulClient::create_discover_task(
const std::string& service_namespace,
const std::string& service_name,
int retry_max,
consul_callback_t cb)
{
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>µ<EFBFBD> Consul <20><><EFBFBD><EFBFBD>
WFConsulTask *task = new WFConsulTask(this->proxy_url, service_namespace,
service_name, "", retry_max,
std::move(cb));
task->set_api_type(CONSUL_API_TYPE_DISCOVER); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
task->set_config(this->config); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
return task; // <20><><EFBFBD>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>
WFConsulTask *WFConsulClient::create_list_service_task(
const std::string& service_namespace,
int retry_max,
consul_callback_t cb)
{
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>µ<EFBFBD> Consul <20><><EFBFBD><EFBFBD>
WFConsulTask *task = new WFConsulTask(this->proxy_url, service_namespace,
"", "", retry_max,
std::move(cb));
task->set_api_type(CONSUL_API_TYPE_LIST_SERVICE); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
task->set_config(this->config); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
return task; // <20><><EFBFBD>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
WFConsulTask *WFConsulClient::create_register_task(
const std::string& service_namespace,
const std::string& service_name,
const std::string& service_id,
int retry_max,
consul_callback_t cb)
{
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>µ<EFBFBD> Consul <20><><EFBFBD><EFBFBD>
WFConsulTask *task = new WFConsulTask(this->proxy_url, service_namespace,
service_name, service_id, retry_max,
std::move(cb));
task->set_api_type(CONSUL_API_TYPE_REGISTER); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>
task->set_config(this->config); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
return task; // <20><><EFBFBD>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
WFConsulTask *WFConsulClient::create_deregister_task(
const std::string& service_namespace,
const std::string& service_id,
int retry_max,
consul_callback_t cb)
{
// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>µ<EFBFBD> Consul <20><><EFBFBD><EFBFBD>
WFConsulTask *task = new WFConsulTask(this->proxy_url, service_namespace,
"", service_id, retry_max,
std::move(cb));
task->set_api_type(CONSUL_API_TYPE_DEREGISTER); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>
task->set_config(this->config); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
return task; // <20><><EFBFBD>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD>ĵ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>
static bool create_tagged_address(const ConsulAddress& consul_address,
const std::string& name,
json_object_t *tagged_obj)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַΪ<D6B7>գ<EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7>سɹ<D8B3>
if (consul_address.first.empty())
return true;
// <20><> JSON <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ name <20><>Ƕ<EFBFBD>׶<EFBFBD><D7B6><EFBFBD>
const json_value_t *val = json_object_append(tagged_obj, name.c_str(),
JSON_VALUE_OBJECT);
if (!val) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD> false
return false;
// <20><>ȡ<EFBFBD>´<EFBFBD><C2B4><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD>׶<EFBFBD><D7B6><EFBFBD>
json_object_t *obj = json_value_object(val);
if (!obj) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡʧ<C8A1>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD> false
return false;
// <20><>Ƕ<EFBFBD>׶<EFBFBD><D7B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "Address" <20>ֶ<EFBFBD>
if (!json_object_append(obj, "Address", JSON_VALUE_STRING,
consul_address.first.c_str()))
return false;
// <20><>Ƕ<EFBFBD>׶<EFBFBD><D7B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "Port" <20>ֶ<EFBFBD>
if (!json_object_append(obj, "Port", JSON_VALUE_NUMBER,
(double)consul_address.second))
return false;
return true; // <20><>ַ<EFBFBD><D6B7><EFBFBD>󴴽<EFBFBD><F3B4B4BD>ɹ<EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
static bool create_health_check(const ConsulConfig& config, json_object_t *obj)
{
const json_value_t *val; // <20><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD>ֶεķ<CEB5><C4B7><EFBFBD>ֵ
std::string str; // <20><>ʱ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><E6B4A2><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD>δ<EFBFBD><CEB4><EFBFBD>ý<EFBFBD><C3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>飬ֱ<E9A3AC>ӷ<EFBFBD><D3B7>سɹ<D8B3>
if (!config.get_health_check())
return true;
// <20><> JSON <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "Check" <20>ֶ<EFBFBD>
val = json_object_append(obj, "Check", JSON_VALUE_OBJECT);
if (!val) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD> false
return false;
obj = json_value_object(val); // <20><>ȡ "Check" <20><><EFBFBD><EFBFBD>
if (!obj) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡʧ<C8A1>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD> false
return false;
// <20><><EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
str = config.get_check_name();
if (!json_object_append(obj, "Name", JSON_VALUE_STRING, str.c_str()))
return false;
// <20><><EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>ע
str = config.get_check_notes();
if (!json_object_append(obj, "Notes", JSON_VALUE_STRING, str.c_str()))
return false;
// <20><><EFBFBD>ӽ<EFBFBD><D3BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HTTP URL
str = config.get_check_http_url();
if (!str.empty()) // <20><><EFBFBD><EFBFBD> URL <20><>Ϊ<EFBFBD><CEAA>
{
if (!json_object_append(obj, "HTTP", JSON_VALUE_STRING, str.c_str()))
return false;
// <20><><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD>
str = config.get_check_http_method();
if (!json_object_append(obj, "Method", JSON_VALUE_STRING, str.c_str()))
return false;
// <20><><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
str = config.get_http_body();
if (!json_object_append(obj, "Body", JSON_VALUE_STRING, str.c_str()))
return false;
// <20><><EFBFBD><EFBFBD> HTTP ͷ<><CDB7><EFBFBD><EFBFBD>Ϣ
val = json_object_append(obj, "Header", JSON_VALUE_OBJECT);
if (!val)
return false;
json_object_t *header_obj = json_value_object(val);
if (!header_obj)
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> HTTP ͷ<><CDB7><EFBFBD>ֶ<EFBFBD>
for (const auto& header : *config.get_http_headers())
{
val = json_object_append(header_obj, header.first.c_str(),
JSON_VALUE_ARRAY);
if (!val)
return false;
json_array_t *arr = json_value_array(val);
if (!arr)
return false;
// <20><><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD>ֶζ<D6B6>Ӧ<EFBFBD>Ķ<EFBFBD><C4B6><EFBFBD>ֵ
for (const auto& value : header.second)
{
if (!json_array_append(arr, JSON_VALUE_STRING, value.c_str()))
return false;
}
}
}
// <20><><EFBFBD><EFBFBD> TCP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
str = config.get_check_tcp();
if (!str.empty())
{
if (!json_object_append(obj, "TCP", JSON_VALUE_STRING, str.c_str()))
return false;
}
// <20><><EFBFBD>ӳ<EFBFBD>ʼ״̬
str = config.get_initial_status();
if (!json_object_append(obj, "Status", JSON_VALUE_STRING, str.c_str()))
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD>Զ<EFBFBD>ע<EFBFBD><D7A2>ʱ<EFBFBD><CAB1>
str = convert_time_to_str(config.get_auto_deregister_time());
if (!json_object_append(obj, "DeregisterCriticalServiceAfter",
JSON_VALUE_STRING, str.c_str()))
return false;
// <20><><EFBFBD>Ӽ<EFBFBD><D3BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>
str = convert_time_to_str(config.get_check_interval());
if (!json_object_append(obj, "Interval", JSON_VALUE_STRING, str.c_str()))
return false;
// <20><><EFBFBD>Ӽ<EFBFBD><D3BC>鳬ʱʱ<CAB1><CAB1>
str = convert_time_to_str(config.get_check_timeout());
if (!json_object_append(obj, "Timeout", JSON_VALUE_STRING, str.c_str()))
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (!json_object_append(obj, "SuccessBeforePassing", JSON_VALUE_NUMBER,
(double)config.get_success_times()))
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD>ܴ<EFBFBD><DCB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (!json_object_append(obj, "FailuresBeforeCritical", JSON_VALUE_NUMBER,
(double)config.get_failure_times()))
return false;
return true; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD>ɹ<EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
static bool create_register_request(const json_value_t *root,
const struct ConsulService *service,
const ConsulConfig& config)
{
const json_value_t *val; // <20><>ʱ<EFBFBD>洢 JSON ֵ
json_object_t *obj; // <20><>ʱ<EFBFBD>洢 JSON <20><><EFBFBD><EFBFBD>
obj = json_value_object(root); // <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (!obj)
return false;
// <20><><EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD> ID
if (!json_object_append(obj, "ID", JSON_VALUE_STRING,
service->service_id.c_str()))
return false;
// <20><><EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (!json_object_append(obj, "Name", JSON_VALUE_STRING,
service->service_name.c_str()))
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD><D5BC>ǿգ<C7BF><D5A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>
if (!service->service_namespace.empty())
{
if (!json_object_append(obj, "ns", JSON_VALUE_STRING,
service->service_namespace.c_str()))
return false;
}
// <20><><EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD><C7A9><EFBFBD><EFBFBD>
val = json_object_append(obj, "Tags", JSON_VALUE_ARRAY);
if (!val)
return false;
json_array_t *arr = json_value_array(val);
if (!arr)
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>ǩ
for (const auto& tag : service->tags)
{
if (!json_array_append(arr, JSON_VALUE_STRING, tag.c_str()))
return false;
}
// <20><><EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD><EFBFBD><EFBFBD>ַ
if (!json_object_append(obj, "Address", JSON_VALUE_STRING,
service->service_address.first.c_str()))
return false;
// <20><><EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD><EFBFBD>˿<EFBFBD>
if (!json_object_append(obj, "Port", JSON_VALUE_NUMBER,
(double)service->service_address.second))
return false;
// <20><><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD>ݶ<EFBFBD><DDB6><EFBFBD>
val = json_object_append(obj, "Meta", JSON_VALUE_OBJECT);
if (!val)
return false;
json_object_t *meta_obj = json_value_object(val);
if (!meta_obj)
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>
for (const auto& meta_kv : service->meta)
{
if (!json_object_append(meta_obj, meta_kv.first.c_str(),
JSON_VALUE_STRING, meta_kv.second.c_str()))
return false;
}
// <20><><EFBFBD>ӱ<EFBFBD>ǩ<EFBFBD><C7A9><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
int type = service->tag_override ? JSON_VALUE_TRUE : JSON_VALUE_FALSE;
if (!json_object_append(obj, "EnableTagOverride", type))
return false;
// <20><><EFBFBD>Ӵ<EFBFBD><D3B4><EFBFBD>ǩ<EFBFBD>ĵ<EFBFBD>ַ
val = json_object_append(obj, "TaggedAddresses", JSON_VALUE_OBJECT);
if (!val)
return false;
json_object_t *tagged_obj = json_value_object(val);
if (!tagged_obj)
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵Ĵ<CDB5><C4B4><EFBFBD>ǩ<EFBFBD><C7A9>ַ
if (!create_tagged_address(service->lan, "lan", tagged_obj))
return false;
if (!create_tagged_address(service->lan_ipv4, "lan_ipv4", tagged_obj))
return false;
if (!create_tagged_address(service->lan_ipv6, "lan_ipv6", tagged_obj))
return false;
if (!create_tagged_address(service->virtual_address, "virtual", tagged_obj))
return false;
if (!create_tagged_address(service->wan, "wan", tagged_obj))
return false;
if (!create_tagged_address(service->wan_ipv4, "wan_ipv4", tagged_obj))
return false;
if (!create_tagged_address(service->wan_ipv6, "wan_ipv6", tagged_obj))
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (!create_health_check(config, obj))
return false;
return true; // <20><><EFBFBD><EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD>󴴽<EFBFBD><F3B4B4BD>ɹ<EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD>
static bool parse_list_service_result(const json_value_t *root,
std::vector<struct ConsulServiceTags>& result)
{
const json_object_t *obj; // <20>洢 JSON <20><><EFBFBD><EFBFBD>
const json_value_t *val; // <20>洢 JSON ֵ
const json_array_t *arr; // <20>洢 JSON <20><><EFBFBD><EFBFBD>
const char *key; // <20><EFBFBD><E6B4A2>
const char *str; // <20><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>ֵ
// <20><><EFBFBD><EFBFBD>ֵת<D6B5><D7AA>Ϊ JSON <20><><EFBFBD><EFBFBD>
obj = json_value_object(root);
if (!obj) // <20><><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>ʧ<EFBFBD>ܣ<EFBFBD><DCA3><EFBFBD><EFBFBD><EFBFBD> false
return false;
// <20><><EFBFBD><EFBFBD> JSON <20><><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>
json_object_for_each(key, val, obj)
{
struct ConsulServiceTags instance; // <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǩʵ<C7A9><CAB5>
instance.service_name = key; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
arr = json_value_array(val); // <20><>ȡֵ<C8A1><D6B5>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>
if (!arr) // <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E9A3AC><EFBFBD><EFBFBD> false
return false;
const json_value_t *tag_val; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF>ֵ
json_array_for_each(tag_val, arr)
{
str = json_value_string(tag_val); // <20><>ȡֵ<C8A1><D6B5><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ʽ
if (!str) // <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> false
return false;
instance.tags.emplace_back(str); // <20><><EFBFBD><EFBFBD>ǩ<EFBFBD><C7A9><EFBFBD>ӵ<EFBFBD>ʵ<EFBFBD><CAB5>
}
result.emplace_back(std::move(instance)); // <20><>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD><D3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
}
return true; // <20><><EFBFBD>سɹ<D8B3>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽڵ<D6BD><DAB5><EFBFBD>Ϣ
static bool parse_discover_node(const json_object_t *obj,
struct ConsulServiceInstance *instance)
{
const json_value_t *val; // <20>洢 JSON ֵ
const char *str; // <20><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>ֵ
// <20><><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD> "Node" <20><>Ϣ
val = json_object_find("Node", obj);
if (!val)
return false;
obj = json_value_object(val); // <20><>ȡ "Node" <20><><EFBFBD><EFBFBD>
if (!obj)
return false;
// <20><>ȡ "ID" <20>ֶ<EFBFBD>
val = json_object_find("ID", obj);
if (!val)
return false;
str = json_value_string(val); // ת<><D7AA>Ϊ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
if (!str)
return false;
instance->node_id = str; // <20><><EFBFBD>ýڵ<C3BD> ID
// <20><>ȡ "Node" <20>ֶ<EFBFBD>
val = json_object_find("Node", obj);
if (!val)
return false;
str = json_value_string(val);
if (!str)
return false;
instance->node_name = str; // <20><><EFBFBD>ýڵ<C3BD><DAB5><EFBFBD><EFBFBD><EFBFBD>
// <20><>ȡ "Address" <20>ֶ<EFBFBD>
val = json_object_find("Address", obj);
if (!val)
return false;
str = json_value_string(val);
if (!str)
return false;
instance->node_address = str; // <20><><EFBFBD>ýڵ<C3BD><DAB5><EFBFBD>ַ
// <20><>ȡ "Datacenter" <20>ֶ<EFBFBD>
val = json_object_find("Datacenter", obj);
if (!val)
return false;
str = json_value_string(val);
if (!str)
return false;
instance->dc = str; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> "Meta" <20><>Ϣ
val = json_object_find("Meta", obj);
if (!val)
return false;
const json_object_t *meta_obj = json_value_object(val); // <20><>ȡ "Meta" <20><><EFBFBD><EFBFBD>
if (!meta_obj)
return false;
const char *meta_k; // <20>洢Ԫ<E6B4A2><D4AA><EFBFBD>ݼ<EFBFBD>
const json_value_t *meta_v; // <20>洢Ԫ<E6B4A2><D4AA><EFBFBD><EFBFBD>ֵ
// <20><><EFBFBD><EFBFBD> "Meta" <20><><EFBFBD><EFBFBD>
json_object_for_each(meta_k, meta_v, meta_obj)
{
str = json_value_string(meta_v); // <20><>ȡԪ<C8A1><D4AA><EFBFBD><EFBFBD>ֵ
if (!str)
return false;
instance->node_meta[meta_k] = str; // <20><><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD>ݼ<EFBFBD>ֵ<EFBFBD><D6B5>
}
// <20><>ȡ "CreateIndex" <20>ֶ<EFBFBD>
val = json_object_find("CreateIndex", obj);
if (val)
instance->create_index = json_value_number(val); // <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><>ȡ "ModifyIndex" <20>ֶ<EFBFBD>
val = json_object_find("ModifyIndex", obj);
if (val)
instance->modify_index = json_value_number(val); // <20><><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD><DEB8><EFBFBD><EFBFBD><EFBFBD>
return true; // <20><><EFBFBD>سɹ<D8B3>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>
static bool parse_discover_result(const json_value_t *root,
std::vector<struct ConsulServiceInstance>& result)
{
const json_array_t *arr = json_value_array(root); // <20><>ȡ JSON <20><><EFBFBD><EFBFBD>
const json_value_t *val; // <20><EFBFBD><E6B4A2><EFBFBD><EFBFBD>ֵ
const json_object_t *obj; // <20>洢 JSON <20><><EFBFBD><EFBFBD>
if (!arr) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E9A3AC><EFBFBD><EFBFBD> false
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
json_array_for_each(val, arr)
{
struct ConsulServiceInstance instance; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>
obj = json_value_object(val); // <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>еĶ<D0B5><C4B6><EFBFBD>
if (!obj)
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>Ϣ
if (!parse_discover_node(obj, &instance))
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
if (!parse_service(obj, &instance.service))
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
parse_health_check(obj, &instance);
result.emplace_back(std::move(instance)); // <20><><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>б<EFBFBD>
}
return true; // <20><><EFBFBD>سɹ<D8B3>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
static bool parse_service(const json_object_t *obj,
struct ConsulService *service)
{
const json_value_t *val; // <20><><EFBFBD>ڴ洢 JSON ֵ
const char *str; // <20><><EFBFBD>ڴ洢<DAB4>ַ<EFBFBD><D6B7><EFBFBD>ֵ
// <20><>ȡ "Service" <20><><EFBFBD><EFBFBD>
val = json_object_find("Service", obj);
if (!val)
return false;
obj = json_value_object(val); // <20><>ֵת<D6B5><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>
if (!obj)
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ID
val = json_object_find("ID", obj);
if (!val)
return false;
str = json_value_string(val); // <20><>ֵת<D6B5><D7AA>Ϊ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
if (!str)
return false;
service->service_id = str; // <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD> ID
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
val = json_object_find("Service", obj);
if (!val)
return false;
str = json_value_string(val);
if (!str)
return false;
service->service_name = str; // <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>
val = json_object_find("Namespace", obj);
if (val)
{
str = json_value_string(val);
if (!str)
return false;
service->service_namespace = str; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ռ<EFBFBD>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
val = json_object_find("Address", obj);
if (!val)
return false;
str = json_value_string(val);
if (!str)
return false;
service->service_address.first = str; // <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD>ַ
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˿<EFBFBD>
val = json_object_find("Port", obj);
if (!val)
return false;
service->service_address.second = json_value_number(val); // <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD>˿<EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD><C7A9>ַ
val = json_object_find("TaggedAddresses", obj);
if (!val)
return false;
parse_tagged_address("lan", val, service->lan);
parse_tagged_address("lan_ipv4", val, service->lan_ipv4);
parse_tagged_address("lan_ipv6", val, service->lan_ipv6);
parse_tagged_address("virtual", val, service->virtual_address);
parse_tagged_address("wan", val, service->wan);
parse_tagged_address("wan_ipv4", val, service->wan_ipv4);
parse_tagged_address("wan_ipv6", val, service->wan_ipv6);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD>б<EFBFBD>
val = json_object_find("Tags", obj);
if (!val)
return false;
const json_array_t *tags_arr = json_value_array(val); // <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
if (tags_arr)
{
const json_value_t *tags_value;
json_array_for_each(tags_value, tags_arr) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
str = json_value_string(tags_value); // <20><>ȡ<EFBFBD><C8A1>ǩ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
if (!str)
return false;
service->tags.emplace_back(str); // <20><><EFBFBD>ӱ<EFBFBD>ǩ<EFBFBD><C7A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
}
// <20><><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>
val = json_object_find("Meta", obj);
if (!val)
return false;
const json_object_t *meta_obj = json_value_object(val); // <20><>ȡԪ<C8A1><D4AA><EFBFBD>ݶ<EFBFBD><DDB6><EFBFBD>
if (!meta_obj)
return false;
const char *meta_k;
const json_value_t *meta_v;
json_object_for_each(meta_k, meta_v, meta_obj) // <20><><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD><EFBFBD>
{
str = json_value_string(meta_v);
if (!str)
return false;
service->meta[meta_k] = str; // <20><><EFBFBD><EFBFBD>Ԫ<EFBFBD><D4AA><EFBFBD>ݼ<EFBFBD>ֵ<EFBFBD><D6B5>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǩ<EFBFBD><C7A9><EFBFBD><EFBFBD>ѡ<EFBFBD><D1A1>
val = json_object_find("EnableTagOverride", obj);
if (val)
service->tag_override = (json_value_type(val) == JSON_VALUE_TRUE);
return true; // <20><><EFBFBD>سɹ<D8B3>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
static bool parse_health_check(const json_object_t *obj,
struct ConsulServiceInstance *instance)
{
const json_value_t *val; // <20>洢 JSON ֵ
const char *str; // <20><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>ֵ
// <20><>ȡ "Checks" <20><><EFBFBD><EFBFBD>
val = json_object_find("Checks", obj);
if (!val)
return false;
const json_array_t *check_arr = json_value_array(val); // ת<><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>
if (!check_arr)
return false;
const json_value_t *arr_val;
json_array_for_each(arr_val, check_arr) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
obj = json_value_object(arr_val); // <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>еĶ<D0B5><C4B6><EFBFBD>
if (!obj)
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
val = json_object_find("ServiceName", obj);
if (!val)
return false;
str = json_value_string(val);
if (!str)
return false;
std::string check_service_name = str;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ID
val = json_object_find("ServiceID", obj);
if (!val)
return false;
str = json_value_string(val);
if (!str)
return false;
std::string check_service_id = str;
if (check_service_id.empty() || check_service_name.empty())
continue;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ID
val = json_object_find("CheckID", obj);
if (!val)
return false;
str = json_value_string(val);
if (!str)
return false;
instance->check_id = str;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
val = json_object_find("Name", obj);
if (!val)
return false;
str = json_value_string(val);
if (!str)
return false;
instance->check_name = str;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״̬
val = json_object_find("Status", obj);
if (!val)
return false;
str = json_value_string(val);
if (!str)
return false;
instance->check_status = str;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע
val = json_object_find("Notes", obj);
if (val)
{
str = json_value_string(val);
if (!str)
return false;
instance->check_notes = str;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
val = json_object_find("Output", obj);
if (val)
{
str = json_value_string(val);
if (!str)
return false;
instance->check_output = str;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
val = json_object_find("Type", obj);
if (val)
{
str = json_value_string(val);
if (!str)
return false;
instance->check_type = str;
}
break; // ֻ<><D6BB><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>Ч<EFBFBD>Ľ<EFBFBD><C4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
return true; // <20><><EFBFBD>سɹ<D8B3>
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>
static bool parse_discover_result(const json_value_t *root,
std::vector<struct ConsulServiceInstance>& result)
{
const json_array_t *arr = json_value_array(root); // ת<><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>
const json_value_t *val; // <20><EFBFBD><E6B4A2><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ֵ
const json_object_t *obj; // <20>洢 JSON <20><><EFBFBD><EFBFBD>
if (!arr)
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
json_array_for_each(val, arr)
{
struct ConsulServiceInstance instance; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5>
obj = json_value_object(val); // <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD>еĶ<D0B5><C4B6><EFBFBD>
if (!obj)
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>Ϣ
if (!parse_discover_node(obj, &instance))
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ
if (!parse_service(obj, &instance.service))
return false;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
parse_health_check(obj, &instance);
result.emplace_back(std::move(instance)); // <20><><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
return true; // <20><><EFBFBD>سɹ<D8B3>
}
// <20><>ӡ JSON <20><><EFBFBD>󣬵ݹ<F3A3ACB5><DDB9>ؽ<EFBFBD><D8BD><EFBFBD>ת<EFBFBD><D7AA>Ϊ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ʽ
static void print_json_object(const json_object_t *obj, int depth,
std::string& json_str)
{
const char *name; // JSON <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>
const json_value_t *val; // JSON <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
int n = 0; // <20><>ֵ<EFBFBD>Եļ<D4B5><C4BC><EFBFBD><EFBFBD><EFBFBD>
int i;
json_str += "{\n"; // <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> JSON <20><><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>
json_object_for_each(name, val, obj)
{
if (n != 0) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>ֵ<EFBFBD>ԣ<EFBFBD><D4A3><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6>Ż<EFBFBD><C5BB><EFBFBD>
json_str += ",\n";
n++; // <20><>ֵ<EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD><EFBFBD> 1
for (i = 0; i < depth + 1; i++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
json_str += " ";
// <20><><EFBFBD>Ӽ<EFBFBD>
json_str += "\"";
json_str += name;
json_str += "\": ";
// <20>ݹ<EFBFBD><DDB9><EFBFBD>ӡֵ
print_json_value(val, depth + 1, json_str);
}
json_str += "\n"; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD>
for (i = 0; i < depth; i++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
json_str += " ";
json_str += "}"; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><>ӡ JSON <20><><EFBFBD><EFBFBD>ݹ<EFBFBD><DDB9>ؽ<EFBFBD><D8BD><EFBFBD>ת<EFBFBD><D7AA>Ϊ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ʽ
static void print_json_array(const json_array_t *arr, int depth,
std::string& json_str)
{
const json_value_t *val; // JSON <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
int n = 0; // <20><><EFBFBD><EFBFBD>ֵ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
int i;
json_str += "[\n"; // <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> JSON <20><><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>ÿ<EFBFBD><C3BF>ֵ
json_array_for_each(val, arr)
{
if (n != 0) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD>һ<EFBFBD><D2BB>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>Ӷ<EFBFBD><D3B6>Ż<EFBFBD><C5BB><EFBFBD>
json_str += ",\n";
n++; // ֵ<><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1
for (i = 0; i < depth + 1; i++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
json_str += " ";
// <20>ݹ<EFBFBD><DDB9><EFBFBD>ӡֵ
print_json_value(val, depth + 1, json_str);
}
json_str += "\n"; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݽ<EFBFBD><DDBD><EFBFBD>
for (i = 0; i < depth; i++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
json_str += " ";
json_str += "]"; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
// <20><>ӡ JSON <20>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ת<EFBFBD><D7AA>
static void print_json_string(const char *str, std::string& json_str)
{
json_str += "\""; // <20><>ʼ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD>е<EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD>ַ<EFBFBD>
while (*str)
{
switch (*str)
{
case '\r': // <20>س<EFBFBD><D8B3><EFBFBD>ת<EFBFBD><D7AA>
json_str += "\\r";
break;
case '\n': // <20><><EFBFBD>з<EFBFBD>ת<EFBFBD><D7AA>
json_str += "\\n";
break;
case '\f': // <20><>ҳ<EFBFBD><D2B3>ת<EFBFBD><D7AA>
json_str += "\\f";
break;
case '\b': // <20>˸<EFBFBD><CBB8><EFBFBD>ת<EFBFBD><D7AA>
json_str += "\\b";
break;
case '\"': // ˫<><CBAB><EFBFBD><EFBFBD>ת<EFBFBD><D7AA>
json_str += "\\\"";
break;
case '\t': // <20>Ʊ<EFBFBD><C6B1><EFBFBD>ת<EFBFBD><D7AA>
json_str += "\\t";
break;
case '\\': // <20><>б<EFBFBD><D0B1>ת<EFBFBD><D7AA>
json_str += "\\\\";
break;
default: // <20><><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
json_str += *str;
break;
}
str++; // ָ<><D6B8><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ַ<EFBFBD>
}
json_str += "\""; // <20><><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
}
// <20><>ӡ JSON <20><><EFBFBD><EFBFBD>
static void print_json_number(double number, std::string& json_str)
{
long long integer = number; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (integer == number) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
json_str += std::to_string(integer); // ת<><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
else // <20><><EFBFBD><EFBFBD><EFBFBD>Ǹ<EFBFBD><C7B8><EFBFBD><EFBFBD><EFBFBD>
json_str += std::to_string(number); // ת<><D7AA>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
}
// <20><><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ӡ JSON ֵ
static void print_json_value(const json_value_t *val, int depth,
std::string& json_str)
{
switch (json_value_type(val)) // <20><>ȡֵ<C8A1><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
case JSON_VALUE_STRING: // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD>
print_json_string(json_value_string(val), json_str);
break;
case JSON_VALUE_NUMBER: // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
print_json_number(json_value_number(val), json_str);
break;
case JSON_VALUE_OBJECT: // <20><><EFBFBD><EFBFBD><EFBFBD>Ƕ<EFBFBD><C7B6><EFBFBD>
print_json_object(json_value_object(val), depth, json_str);
break;
case JSON_VALUE_ARRAY: // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
print_json_array(json_value_array(val), depth, json_str);
break;
case JSON_VALUE_TRUE: // <20><><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><C7B2><EFBFBD>ֵ true
json_str += "true";
break;
case JSON_VALUE_FALSE: // <20><><EFBFBD><EFBFBD><EFBFBD>Dz<EFBFBD><C7B2><EFBFBD>ֵ false
json_str += "false";
break;
case JSON_VALUE_NULL: // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> null
json_str += "null";
break;
}
}