Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
|
378861e9c9 | |
|
4542817ed2 |
|
@ -1,4 +1,5 @@
|
|||
---
|
||||
SortIncludes: Never
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
|
||||
|
|
|
@ -5,16 +5,12 @@
|
|||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(lldb) Launch",
|
||||
"type": "cppdbg",
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/cmake-build-debug/nginx_nacos",
|
||||
"name": "Launch",
|
||||
"program": "${workspaceRoot}/cmake-build-debug/nginx_nacos",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}/cmake-build-debug",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "lldb",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "cmake build"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -5,29 +5,45 @@
|
|||
},
|
||||
"tasks": [
|
||||
{
|
||||
"type": "shell",
|
||||
"label": "cmake",
|
||||
"command": "cmake",
|
||||
"args": [
|
||||
"-DCMAKE_BUILD_TYPE=Debug",
|
||||
".."
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "make",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"command": "make",
|
||||
"args": ["nginx_nacos"]
|
||||
"args": [
|
||||
"-j",
|
||||
"4"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "cmake build",
|
||||
"dependsOn": [
|
||||
"mkdir",
|
||||
"cmake",
|
||||
"make"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "process",
|
||||
"command": "/usr/bin/env",
|
||||
"args": [
|
||||
"CC=clang",
|
||||
"CFLAGS=-g -Wall",
|
||||
"make",
|
||||
"${fileBasenameNoExtension}"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${fileDirname}"
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"label": "makelldb: selected file"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -70,6 +70,10 @@ set(NGX_C_FILES nginx/src/core/nginx.c
|
|||
nginx/src/os/unix/ngx_user.c
|
||||
nginx/src/os/unix/ngx_dlopen.c
|
||||
nginx/src/os/unix/ngx_process_cycle.c
|
||||
nginx/src/os/unix/ngx_linux_init.c
|
||||
nginx/src/event/modules/ngx_epoll_module.c
|
||||
nginx/src/os/unix/ngx_linux_sendfile_chain.c
|
||||
nginx/src/core/ngx_bpf.c
|
||||
nginx/src/event/ngx_event_openssl.c
|
||||
nginx/src/event/ngx_event_openssl_stapling.c
|
||||
nginx/src/core/ngx_regex.c
|
||||
|
@ -85,6 +89,8 @@ set(NGX_C_FILES nginx/src/core/nginx.c
|
|||
nginx/src/http/ngx_http_upstream.c
|
||||
nginx/src/http/ngx_http_upstream_round_robin.c
|
||||
nginx/src/http/ngx_http_file_cache.c
|
||||
nginx/src/http/ngx_http_huff_decode.c
|
||||
nginx/src/http/ngx_http_huff_encode.c
|
||||
nginx/src/http/ngx_http_write_filter_module.c
|
||||
nginx/src/http/ngx_http_header_filter_module.c
|
||||
nginx/src/http/modules/ngx_http_chunked_filter_module.c
|
||||
|
@ -101,8 +107,6 @@ set(NGX_C_FILES nginx/src/core/nginx.c
|
|||
nginx/src/http/v2/ngx_http_v2.c
|
||||
nginx/src/http/v2/ngx_http_v2_table.c
|
||||
nginx/src/http/v2/ngx_http_v2_encode.c
|
||||
nginx/src/http/v2/ngx_http_v2_huff_decode.c
|
||||
nginx/src/http/v2/ngx_http_v2_huff_encode.c
|
||||
nginx/src/http/v2/ngx_http_v2_module.c
|
||||
nginx/src/http/modules/ngx_http_static_module.c
|
||||
nginx/src/http/modules/ngx_http_autoindex_module.c
|
||||
|
|
15
README.md
15
README.md
|
@ -226,10 +226,23 @@ upstream backend {
|
|||
# server 127.0.0.1:8080;
|
||||
# 如果provider使用的spring,service_name 要和 spring.application.name一致
|
||||
# 不知道 provider 端怎么写请参考 https://github.com/zhwaaaaaa/springmvc-nacos-registry
|
||||
nacos_subscribe_service service_name=springmvc-nacos-demo group=DEFAULT_GROUP;
|
||||
# weight * nacos_weight 是 nginx 的权重,默认1 max_fails=1 fail_timeout 对应 nginx 的server 配置
|
||||
nacos_subscribe_service service_name=springmvc-nacos-demo group=DEFAULT_GROUP weight=1 max_fails=1 fail_timeout=10s;
|
||||
}
|
||||
```
|
||||
|
||||
### nacos_use_cluster
|
||||
如果指定,则对应使用 cluster ip. 支持变量和字面量组合. 不指定,则使用所有集群 ip
|
||||
```
|
||||
set $cluster "DEFAULT";
|
||||
|
||||
upstream backend {
|
||||
nacos_subscribe_service service_name=springmvc-nacos-demo group=DEFAULT_GROUP weight=1 max_fails=1 fail_timeout=10s;
|
||||
nacos_use_cluster $cluster;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### nacos_config_var
|
||||
订阅 nacos 的配置,nginx把它写到 http 变量中。这个配置项可以出现在 http server location if {} 块中。
|
||||
```
|
||||
|
|
2
build.sh
2
build.sh
|
@ -18,7 +18,7 @@ patch -p1 < ../patch/nginx.patch
|
|||
--with-http_ssl_module \
|
||||
--add-module=../modules/auxiliary \
|
||||
--add-module=../modules/nacos \
|
||||
--prefix=.. \
|
||||
--prefix= \
|
||||
--conf-path=conf/my.conf \
|
||||
--error-log-path=objs/logs/error.log \
|
||||
--pid-path=objs/logs/nginx.pid \
|
||||
|
|
25
conf/my.conf
25
conf/my.conf
|
@ -14,16 +14,16 @@ events {
|
|||
}
|
||||
|
||||
nacos {
|
||||
server_list localhost:8848; # nacos 服务器列表,空格隔开
|
||||
grpc_server_list localhost:9848; # nacos grpc服务器列表,空格隔开
|
||||
server_list 127.0.0.1:8848; # nacos 服务器列表,空格隔开
|
||||
grpc_server_list 127.0.0.1:9848; # nacos grpc服务器列表,空格隔开
|
||||
#udp_port 19999; #udp 端口号
|
||||
#udp_ip 127.0.0.1; #udp ip 地址。
|
||||
#udp_bind 0.0.0.0:19999; # 绑定udp 地址
|
||||
# username "nacos";
|
||||
# password "nacos";
|
||||
error_log cmake-build-debug/logs/nacos.log info;
|
||||
username "nacos";
|
||||
password "nacos";
|
||||
error_log objs/logs/nacos.log info;
|
||||
default_group DEFAULT_GROUP; # 默认的nacos group name
|
||||
cache_dir cmake-build-debug/nacos/;
|
||||
cache_dir objs/nacos/;
|
||||
}
|
||||
http {
|
||||
include mime.types;
|
||||
|
@ -39,26 +39,21 @@ http {
|
|||
|
||||
#gzip on;
|
||||
upstream s {
|
||||
nacos_subscribe_service service_name=springmvc-nacos-demo; # data_id 要和 spring.application.name一致
|
||||
nacos_subscribe_service service_name=springmvc-nacos-demo weight=100 max_fails=1 fail_timeout=10s; # service_name 要和 spring.application.name一致
|
||||
nacos_use_cluster DEFAULT;
|
||||
keepalive 300;
|
||||
}
|
||||
nacos_config_var $n_var data_id=ccccdddddd group=DEFAULT_GROUP md5_var=$dd default=123456;
|
||||
nacos_config_var $n_var data_id=tt.server.route.json group=stg1 md5_var=$dd default=123456;
|
||||
server {
|
||||
listen 9999 default_server;
|
||||
proxy_set_header Connection "";
|
||||
proxy_http_version 1.1;
|
||||
location ^~ / {
|
||||
add_header X-Var-Nacos "$n_var" always;
|
||||
proxy_pass http://s;
|
||||
}
|
||||
|
||||
nacos_config_var $n_bb data_id=aaabbbbccc;
|
||||
|
||||
|
||||
location ^~ /echo {
|
||||
nacos_config_var $n_var data_id=ccdd;
|
||||
add_header X-Var-Nacos "$n_var";
|
||||
return 200 "hear ....n_var: $n_var ... n_bb: $n_bb ....dd: $dd";
|
||||
return 200 "hear ....n_var: $n_var ... ....dd: $dd";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
mkdir -p objs
|
||||
cd objs
|
||||
curl -sSL https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.9-linux-x86.tar.gz -o nanopb.tar.gz
|
||||
|
||||
tar zxvf nanopb.tar.gz
|
||||
mv nanopb-0.4.9-linux-x86 nanopb
|
||||
|
||||
python3 nanopb/generator/nanopb_generator.py backup.proto nacos_grpc_service.proto -I ../modules/nacos
|
|
@ -1,34 +1,18 @@
|
|||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.3.9.8 at Fri Aug 9 21:47:15 2024. */
|
||||
/* Generated by nanopb-0.4.9 */
|
||||
|
||||
#include "backup.pb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(Config, Config, AUTO)
|
||||
|
||||
|
||||
const pb_field_t Config_fields[4] = {
|
||||
PB_FIELD( 1, UINT64 , SINGULAR, STATIC , FIRST, Config, version, version, 0),
|
||||
PB_FIELD( 2, STRING , SINGULAR, CALLBACK, OTHER, Config, content, version, 0),
|
||||
PB_FIELD( 3, STRING , SINGULAR, CALLBACK, OTHER, Config, md5, content, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t Instance_fields[4] = {
|
||||
PB_FIELD( 1, STRING , SINGULAR, CALLBACK, FIRST, Instance, host, host, 0),
|
||||
PB_FIELD( 2, INT32 , SINGULAR, STATIC , OTHER, Instance, port, host, 0),
|
||||
PB_FIELD( 3, INT32 , SINGULAR, STATIC , OTHER, Instance, weight, port, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t Service_fields[3] = {
|
||||
PB_FIELD( 1, UINT64 , SINGULAR, STATIC , FIRST, Service, version, version, 0),
|
||||
PB_FIELD( 2, MESSAGE , REPEATED, CALLBACK, OTHER, Service, instances, version, &Instance_fields),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
PB_BIND(Instance, Instance, AUTO)
|
||||
|
||||
|
||||
PB_BIND(Service, Service, AUTO)
|
||||
|
||||
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
|
|
@ -1,48 +1,44 @@
|
|||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.8 at Fri Aug 9 21:47:15 2024. */
|
||||
/* Generated by nanopb-0.4.9 */
|
||||
|
||||
#ifndef PB_BACKUP_PB_H_INCLUDED
|
||||
#define PB_BACKUP_PB_H_INCLUDED
|
||||
#include <pb/pb.h>
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _Config {
|
||||
uint64_t version;
|
||||
pb_callback_t content;
|
||||
pb_callback_t md5;
|
||||
/* @@protoc_insertion_point(struct:Config) */
|
||||
} Config;
|
||||
|
||||
typedef struct _Instance {
|
||||
pb_callback_t host;
|
||||
int32_t port;
|
||||
int32_t weight;
|
||||
/* @@protoc_insertion_point(struct:Instance) */
|
||||
pb_callback_t cluster;
|
||||
} Instance;
|
||||
|
||||
typedef struct _Service {
|
||||
uint64_t version;
|
||||
pb_callback_t instances;
|
||||
/* @@protoc_insertion_point(struct:Service) */
|
||||
} Service;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define Config_init_default {0, {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define Instance_init_default {{{NULL}, NULL}, 0, 0}
|
||||
#define Instance_init_default {{{NULL}, NULL}, 0, 0, {{NULL}, NULL}}
|
||||
#define Service_init_default {0, {{NULL}, NULL}}
|
||||
#define Config_init_zero {0, {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define Instance_init_zero {{{NULL}, NULL}, 0, 0}
|
||||
#define Instance_init_zero {{{NULL}, NULL}, 0, 0, {{NULL}, NULL}}
|
||||
#define Service_init_zero {0, {{NULL}, NULL}}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
|
@ -52,30 +48,49 @@ typedef struct _Service {
|
|||
#define Instance_host_tag 1
|
||||
#define Instance_port_tag 2
|
||||
#define Instance_weight_tag 3
|
||||
#define Instance_cluster_tag 4
|
||||
#define Service_version_tag 1
|
||||
#define Service_instances_tag 2
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t Config_fields[4];
|
||||
extern const pb_field_t Instance_fields[4];
|
||||
extern const pb_field_t Service_fields[3];
|
||||
#define Config_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT64, version, 1) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, content, 2) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, md5, 3)
|
||||
#define Config_CALLBACK pb_default_field_callback
|
||||
#define Config_DEFAULT NULL
|
||||
|
||||
#define Instance_FIELDLIST(X, a) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, host, 1) \
|
||||
X(a, STATIC, SINGULAR, INT32, port, 2) \
|
||||
X(a, STATIC, SINGULAR, INT32, weight, 3) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, cluster, 4)
|
||||
#define Instance_CALLBACK pb_default_field_callback
|
||||
#define Instance_DEFAULT NULL
|
||||
|
||||
#define Service_FIELDLIST(X, a) \
|
||||
X(a, STATIC, SINGULAR, UINT64, version, 1) \
|
||||
X(a, CALLBACK, REPEATED, MESSAGE, instances, 2)
|
||||
#define Service_CALLBACK pb_default_field_callback
|
||||
#define Service_DEFAULT NULL
|
||||
#define Service_instances_MSGTYPE Instance
|
||||
|
||||
extern const pb_msgdesc_t Config_msg;
|
||||
extern const pb_msgdesc_t Instance_msg;
|
||||
extern const pb_msgdesc_t Service_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define Config_fields &Config_msg
|
||||
#define Instance_fields &Instance_msg
|
||||
#define Service_fields &Service_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* Config_size depends on runtime parameters */
|
||||
/* Instance_size depends on runtime parameters */
|
||||
/* Service_size depends on runtime parameters */
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define BACKUP_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,6 +10,7 @@ message Instance {
|
|||
string host = 1;
|
||||
int32 port = 2;
|
||||
int32 weight = 3;
|
||||
string cluster = 4;
|
||||
}
|
||||
|
||||
message Service {
|
||||
|
|
|
@ -1,73 +1,21 @@
|
|||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.3.9.10 at Mon Jun 3 14:49:02 2024. */
|
||||
/* Generated by nanopb-0.4.9 */
|
||||
|
||||
#include "nacos_grpc_service.pb.h"
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/**
|
||||
* #define PB_FIELD(tag, type, rules, allocation, placement, message, field, prevfield, ptr) \
|
||||
PB_ ## rules ## _ ## allocation(tag, message, field, \
|
||||
PB_DATAOFFSET_ ## placement(message, field, prevfield), \
|
||||
PB_LTYPE_MAP_ ## type, ptr)
|
||||
*/
|
||||
PB_BIND(Any, Any, AUTO)
|
||||
|
||||
|
||||
const pb_field_t google_protobuf_Any_fields[3] = {
|
||||
PB_FIELD( 1, STRING , SINGULAR, CALLBACK, FIRST, google_protobuf_Any, type_url, type_url, 0),
|
||||
PB_FIELD( 2, BYTES , SINGULAR, CALLBACK, OTHER, google_protobuf_Any, value, type_url, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
PB_BIND(Metadata, Metadata, AUTO)
|
||||
|
||||
|
||||
const pb_field_t Metadata_HeadersEntry_fields[3] = {
|
||||
PB_FIELD( 1, STRING , SINGULAR, CALLBACK, FIRST, Metadata_HeadersEntry, key, key, 0),
|
||||
PB_FIELD( 2, STRING , SINGULAR, CALLBACK, OTHER, Metadata_HeadersEntry, value, key, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
|
||||
const pb_field_t Metadata_fields[4] = {
|
||||
PB_FIELD( 3, STRING , SINGULAR, CALLBACK, FIRST, Metadata, type, type, 0),
|
||||
// PB_SINGULAR_CALLBACK(3, Metadata, type, PB_DATAOFFSET_FIRST(Metadata, type, type), PB_LTYPE_MAP_STRING, 0),
|
||||
PB_FIELD( 7, MESSAGE , REPEATED, CALLBACK, OTHER, Metadata, headers, type, &Metadata_HeadersEntry_fields),
|
||||
PB_FIELD( 8, STRING , SINGULAR, CALLBACK, OTHER, Metadata, clientIp, headers, 0),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
PB_BIND(Metadata_HeadersEntry, Metadata_HeadersEntry, AUTO)
|
||||
|
||||
|
||||
const pb_field_t Payload_fields[3] = {
|
||||
PB_FIELD( 2, MESSAGE , SINGULAR, STATIC , FIRST, Payload, metadata, metadata, &Metadata_fields),
|
||||
// PB_SINGULAR_STATIC(2, Payload,metadata, PB_DATAOFFSET_FIRST(Payload, metadata, metadata), PB_LTYPE_MAP_MESSAGE, &Metadata_fields),
|
||||
PB_FIELD( 3, MESSAGE , SINGULAR, STATIC , OTHER, Payload, body, metadata, &google_protobuf_Any_fields),
|
||||
PB_LAST_FIELD
|
||||
};
|
||||
PB_BIND(Payload, Payload, AUTO)
|
||||
|
||||
|
||||
/* Check that field information fits in pb_field_t */
|
||||
#if !defined(PB_FIELD_32BIT)
|
||||
/* If you get an error here, it means that you need to define PB_FIELD_32BIT
|
||||
* compile-time option. You can do that in pb.h or on compiler command line.
|
||||
*
|
||||
* The reason you need to do this is that some of your messages contain tag
|
||||
* numbers or field sizes that are larger than what can fit in 8 or 16 bit
|
||||
* field descriptors.
|
||||
*/
|
||||
PB_STATIC_ASSERT((pb_membersize(Payload, metadata) < 65536 && pb_membersize(Payload, body) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_Metadata_Metadata_HeadersEntry_Payload)
|
||||
#endif
|
||||
|
||||
#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
|
||||
/* If you get an error here, it means that you need to define PB_FIELD_16BIT
|
||||
* compile-time option. You can do that in pb.h or on compiler command line.
|
||||
*
|
||||
* The reason you need to do this is that some of your messages contain tag
|
||||
* numbers or field sizes that are larger than what can fit in the default
|
||||
* 8 bit descriptors.
|
||||
*/
|
||||
PB_STATIC_ASSERT((pb_membersize(Payload, metadata) < 256 && pb_membersize(Payload, body) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_Metadata_Metadata_HeadersEntry_Payload)
|
||||
#endif
|
||||
|
||||
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
|
|
@ -1,106 +1,112 @@
|
|||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.3.9.10 at Mon Jun 3 14:49:02 2024. */
|
||||
/* Generated by nanopb-0.4.9 */
|
||||
|
||||
#ifndef PB_NACOS_GRPC_SERVICE_PB_H_INCLUDED
|
||||
#define PB_NACOS_GRPC_SERVICE_PB_H_INCLUDED
|
||||
#include <pb/pb.h>
|
||||
|
||||
/* @@protoc_insertion_point(includes) */
|
||||
#if PB_PROTO_HEADER_VERSION != 30
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _Any {
|
||||
pb_callback_t type_url;
|
||||
pb_callback_t value;
|
||||
} Any;
|
||||
|
||||
typedef struct _Metadata {
|
||||
pb_callback_t type;
|
||||
pb_callback_t headers;
|
||||
pb_callback_t clientIp;
|
||||
} Metadata;
|
||||
|
||||
typedef struct _Metadata_HeadersEntry {
|
||||
pb_callback_t key;
|
||||
pb_callback_t value;
|
||||
} Metadata_HeadersEntry;
|
||||
|
||||
typedef struct _Payload {
|
||||
bool has_metadata;
|
||||
Metadata metadata;
|
||||
bool has_body;
|
||||
Any body;
|
||||
} Payload;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct google_protobuf_Any {
|
||||
pb_callback_t type_url;
|
||||
pb_callback_t value;
|
||||
/* @@protoc_insertion_point(struct:google_protobuf_Any) */
|
||||
} google_protobuf_Any;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define google_protobuf_Any_init_default \
|
||||
{ \
|
||||
{{NULL}, NULL}, { {NULL}, NULL } \
|
||||
}
|
||||
#define google_protobuf_Any_init_zero \
|
||||
{ \
|
||||
{{NULL}, NULL}, { {NULL}, NULL } \
|
||||
}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define google_protobuf_Any_type_url_tag 1
|
||||
#define google_protobuf_Any_value_tag 2
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t google_protobuf_Any_fields[3];
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct Metadata {
|
||||
pb_callback_t type;
|
||||
pb_callback_t headers;
|
||||
pb_callback_t clientIp;
|
||||
/* @@protoc_insertion_point(struct:Metadata) */
|
||||
} Metadata;
|
||||
|
||||
typedef struct Metadata_HeadersEntry {
|
||||
pb_callback_t key;
|
||||
pb_callback_t value;
|
||||
/* @@protoc_insertion_point(struct:Metadata_HeadersEntry) */
|
||||
} Metadata_HeadersEntry;
|
||||
|
||||
typedef struct Payload {
|
||||
Metadata metadata;
|
||||
google_protobuf_Any body;
|
||||
/* @@protoc_insertion_point(struct:Payload) */
|
||||
} Payload;
|
||||
|
||||
/* Default values for struct fields */
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define Any_init_default {{{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define Metadata_init_default {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define Metadata_HeadersEntry_init_default {{{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define Payload_init_default {Metadata_init_default, google_protobuf_Any_init_default}
|
||||
#define Payload_init_default {false, Metadata_init_default, false, Any_init_default}
|
||||
#define Any_init_zero {{{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define Metadata_init_zero {{{NULL}, NULL}, {{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define Metadata_HeadersEntry_init_zero {{{NULL}, NULL}, {{NULL}, NULL}}
|
||||
#define Payload_init_zero {Metadata_init_zero, google_protobuf_Any_init_zero}
|
||||
#define Payload_init_zero {false, Metadata_init_zero, false, Any_init_zero}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define Any_type_url_tag 1
|
||||
#define Any_value_tag 2
|
||||
#define Metadata_type_tag 3
|
||||
#define Metadata_clientIp_tag 8
|
||||
#define Metadata_headers_tag 7
|
||||
#define Metadata_clientIp_tag 8
|
||||
#define Metadata_HeadersEntry_key_tag 1
|
||||
#define Metadata_HeadersEntry_value_tag 2
|
||||
#define Payload_metadata_tag 2
|
||||
#define Payload_body_tag 3
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
extern const pb_field_t Metadata_fields[4];
|
||||
extern const pb_field_t Metadata_HeadersEntry_fields[3];
|
||||
extern const pb_field_t Payload_fields[3];
|
||||
#define Any_FIELDLIST(X, a) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, type_url, 1) \
|
||||
X(a, CALLBACK, SINGULAR, BYTES, value, 2)
|
||||
#define Any_CALLBACK pb_default_field_callback
|
||||
#define Any_DEFAULT NULL
|
||||
|
||||
#define Metadata_FIELDLIST(X, a) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, type, 3) \
|
||||
X(a, CALLBACK, REPEATED, MESSAGE, headers, 7) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, clientIp, 8)
|
||||
#define Metadata_CALLBACK pb_default_field_callback
|
||||
#define Metadata_DEFAULT NULL
|
||||
#define Metadata_headers_MSGTYPE Metadata_HeadersEntry
|
||||
|
||||
#define Metadata_HeadersEntry_FIELDLIST(X, a) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, key, 1) \
|
||||
X(a, CALLBACK, SINGULAR, STRING, value, 2)
|
||||
#define Metadata_HeadersEntry_CALLBACK pb_default_field_callback
|
||||
#define Metadata_HeadersEntry_DEFAULT NULL
|
||||
|
||||
#define Payload_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, metadata, 2) \
|
||||
X(a, STATIC, OPTIONAL, MESSAGE, body, 3)
|
||||
#define Payload_CALLBACK NULL
|
||||
#define Payload_DEFAULT NULL
|
||||
#define Payload_metadata_MSGTYPE Metadata
|
||||
#define Payload_body_MSGTYPE Any
|
||||
|
||||
extern const pb_msgdesc_t Any_msg;
|
||||
extern const pb_msgdesc_t Metadata_msg;
|
||||
extern const pb_msgdesc_t Metadata_HeadersEntry_msg;
|
||||
extern const pb_msgdesc_t Payload_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define Any_fields &Any_msg
|
||||
#define Metadata_fields &Metadata_msg
|
||||
#define Metadata_HeadersEntry_fields &Metadata_HeadersEntry_msg
|
||||
#define Payload_fields &Payload_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* Any_size depends on runtime parameters */
|
||||
/* Metadata_size depends on runtime parameters */
|
||||
/* Metadata_HeadersEntry_size depends on runtime parameters */
|
||||
/* Payload_size depends on runtime parameters */
|
||||
|
||||
/* Message IDs (where set with "msgid" option) */
|
||||
#ifdef PB_MSGID
|
||||
|
||||
#define NACOS_GRPC_SERVICE_MESSAGES \
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
/* @@protoc_insertion_point(eof) */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
/*
|
||||
* Copyright 1999-2020 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
option java_multiple_files = true;
|
||||
option java_package = "com.alibaba.nacos.api.grpc.auto";
|
||||
|
||||
message Any {
|
||||
string type_url = 1;
|
||||
bytes value = 2;
|
||||
}
|
||||
|
||||
message Metadata {
|
||||
string type = 3;
|
||||
string clientIp = 8;
|
||||
map<string, string> headers = 7;
|
||||
}
|
||||
|
||||
message Payload {
|
||||
Metadata metadata = 2;
|
||||
Any body = 3;
|
||||
}
|
|
@ -13,6 +13,12 @@ typedef struct {
|
|||
ngx_http_upstream_init_pt original_init_upstream;
|
||||
ngx_str_t data_id;
|
||||
ngx_str_t group;
|
||||
ngx_uint_t weight;
|
||||
ngx_uint_t max_fails;
|
||||
time_t fail_timeout;
|
||||
ngx_str_t cluster;
|
||||
ngx_array_t *cluster_lengths;
|
||||
ngx_array_t *cluster_values;
|
||||
} ngx_http_nacos_srv_conf_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -21,7 +27,10 @@ typedef struct {
|
|||
ngx_nacos_key_t *key;
|
||||
ngx_uint_t version;
|
||||
ngx_nacos_service_addrs_t addrs;
|
||||
ngx_http_upstream_srv_conf_t *us;
|
||||
ngx_flag_t use_cluster;
|
||||
ngx_http_upstream_srv_conf_t *origin;
|
||||
ngx_http_upstream_srv_conf_t *us; // no cluster
|
||||
ngx_array_t *clustered_us; // ngx_http_upstream_srv_conf_t
|
||||
} ngx_http_nacos_peers_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -41,14 +50,17 @@ static void *ngx_http_nacos_create_srv_conf(ngx_conf_t *cf);
|
|||
static char *ngx_http_conf_use_nacos_address(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
|
||||
static char *ngx_http_conf_nacos_use_cluster(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf);
|
||||
|
||||
static ngx_int_t ngx_http_nacos_init_upstream(ngx_conf_t *cf,
|
||||
ngx_http_upstream_srv_conf_t *us);
|
||||
|
||||
static ngx_int_t ngx_http_nacos_init_peers(ngx_http_request_t *r,
|
||||
ngx_http_upstream_srv_conf_t *us);
|
||||
|
||||
static ngx_int_t ngx_http_nacos_create_new_us(ngx_http_nacos_peers_t *new_peers,
|
||||
ngx_http_upstream_srv_conf_t *us);
|
||||
static ngx_http_upstream_srv_conf_t *ngx_http_nacos_select_upstream(
|
||||
ngx_http_nacos_peers_t *peers, ngx_str_t *cluster);
|
||||
|
||||
static ngx_http_nacos_peers_t *ngx_http_get_nacos_peers(
|
||||
ngx_http_request_t *r, ngx_http_upstream_srv_conf_t *us);
|
||||
|
@ -83,8 +95,11 @@ static ngx_http_module_t ngx_http_nacos_module_ctx = {
|
|||
};
|
||||
|
||||
static ngx_command_t cmds[] = {
|
||||
{ngx_string("nacos_subscribe_service"), NGX_HTTP_UPS_CONF | NGX_CONF_TAKE12,
|
||||
ngx_http_conf_use_nacos_address, NGX_HTTP_SRV_CONF_OFFSET, 0, NULL},
|
||||
{ngx_string("nacos_subscribe_service"),
|
||||
NGX_HTTP_UPS_CONF | NGX_CONF_1MORE, ngx_http_conf_use_nacos_address,
|
||||
NGX_HTTP_SRV_CONF_OFFSET, 0, NULL},
|
||||
{ngx_string("nacos_use_cluster"), NGX_HTTP_UPS_CONF | NGX_CONF_TAKE1,
|
||||
ngx_http_conf_nacos_use_cluster, NGX_HTTP_SRV_CONF_OFFSET, 0, NULL},
|
||||
ngx_null_command};
|
||||
|
||||
ngx_module_t ngx_http_nacos_upstream_module = {NGX_MODULE_V1,
|
||||
|
@ -103,20 +118,29 @@ ngx_module_t ngx_http_nacos_upstream_module = {NGX_MODULE_V1,
|
|||
static void *ngx_http_nacos_create_srv_conf(ngx_conf_t *cf) {
|
||||
return ngx_pcalloc(cf->pool, sizeof(ngx_http_nacos_srv_conf_t));
|
||||
}
|
||||
static ngx_int_t ngx_http_nacos_add_server(ngx_http_nacos_peers_t *peers,
|
||||
ngx_http_nacos_srv_conf_t *nscf,
|
||||
ngx_pool_t *temp_pool);
|
||||
|
||||
static char *ngx_http_conf_use_nacos_address(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf) {
|
||||
ngx_http_nacos_srv_conf_t *nlcf = conf;
|
||||
ngx_uint_t i;
|
||||
ngx_uint_t n = cf->args->nelts;
|
||||
ngx_str_t *value = cf->args->elts;
|
||||
ngx_str_t *value = cf->args->elts, s;
|
||||
ngx_nacos_sub_t tmp;
|
||||
ngx_nacos_main_conf_t *mf;
|
||||
ngx_int_t weight, max_fails;
|
||||
time_t fail_timeout;
|
||||
|
||||
if (nlcf->uscf) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
weight = 1;
|
||||
max_fails = 1;
|
||||
fail_timeout = 10;
|
||||
|
||||
ngx_memzero(&tmp, sizeof(tmp));
|
||||
|
||||
for (i = 1; i < n; ++i) {
|
||||
|
@ -131,6 +155,62 @@ static char *ngx_http_conf_use_nacos_address(ngx_conf_t *cf, ngx_command_t *cmd,
|
|||
tmp.group.len = value[i].len - 6;
|
||||
continue;
|
||||
}
|
||||
if (value[i].len > 7 && ngx_strncmp(value[i].data, "weight=", 7) == 0) {
|
||||
weight = ngx_atoi(value[i].data + 7, value[i].len - 7);
|
||||
if (weight <= 0) {
|
||||
ngx_conf_log_error(
|
||||
NGX_LOG_EMERG, cf, 0,
|
||||
"weight= must be number: invalid parameter \"%V\"",
|
||||
&value[i]);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value[i].len > 10 &&
|
||||
ngx_strncmp(value[i].data, "max_fails=", 10) == 0) {
|
||||
max_fails = ngx_atoi(value[i].data + 10, value[i].len - 10);
|
||||
if (max_fails < 0) {
|
||||
ngx_conf_log_error(
|
||||
NGX_LOG_EMERG, cf, 0,
|
||||
"max_fails= must be number: invalid parameter \"%V\"",
|
||||
&value[i]);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value[i].len > 10 &&
|
||||
ngx_strncmp(value[i].data, "max_fails=", 10) == 0) {
|
||||
max_fails = ngx_atoi(value[i].data + 10, value[i].len - 10);
|
||||
if (max_fails < 0) {
|
||||
ngx_conf_log_error(
|
||||
NGX_LOG_EMERG, cf, 0,
|
||||
"max_fails= must be number: invalid parameter \"%V\"",
|
||||
&value[i]);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value[i].len > 13 &&
|
||||
ngx_strncmp(value[i].data, "fail_timeout=", 13) == 0) {
|
||||
s.len = value[i].len - 13;
|
||||
s.data = &value[i].data[13];
|
||||
|
||||
fail_timeout = ngx_parse_time(&s, 1);
|
||||
|
||||
if (fail_timeout == (time_t) NGX_ERROR) {
|
||||
ngx_conf_log_error(
|
||||
NGX_LOG_EMERG, cf, 0,
|
||||
"fail_timeout= must be time: invalid parameter \"%V\"",
|
||||
&value[i]);
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
|
||||
&value[i]);
|
||||
return NGX_CONF_ERROR;
|
||||
|
@ -143,6 +223,10 @@ static char *ngx_http_conf_use_nacos_address(ngx_conf_t *cf, ngx_command_t *cmd,
|
|||
|
||||
nlcf->data_id = tmp.data_id;
|
||||
nlcf->group = tmp.group;
|
||||
nlcf->weight = weight;
|
||||
nlcf->max_fails = max_fails;
|
||||
nlcf->fail_timeout = fail_timeout;
|
||||
|
||||
nlcf->uscf =
|
||||
ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
|
||||
nlcf->original_init_upstream = nlcf->uscf->peer.init_upstream;
|
||||
|
@ -161,6 +245,40 @@ static char *ngx_http_conf_use_nacos_address(ngx_conf_t *cf, ngx_command_t *cmd,
|
|||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
static char *ngx_http_conf_nacos_use_cluster(ngx_conf_t *cf, ngx_command_t *cmd,
|
||||
void *conf) {
|
||||
ngx_uint_t n;
|
||||
ngx_http_script_compile_t sc;
|
||||
ngx_str_t *value;
|
||||
ngx_http_nacos_srv_conf_t *nscf = conf;
|
||||
|
||||
if (nscf->cluster_lengths != NULL || nscf->cluster.len > 0) {
|
||||
return "is duplicate";
|
||||
}
|
||||
|
||||
value = cf->args->elts;
|
||||
nscf->cluster = value[1];
|
||||
|
||||
n = ngx_http_script_variables_count(&nscf->cluster);
|
||||
ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
|
||||
sc.variables = n;
|
||||
|
||||
if (n) {
|
||||
sc.cf = cf;
|
||||
sc.source = &nscf->cluster;
|
||||
sc.lengths = &nscf->cluster_lengths;
|
||||
sc.values = &nscf->cluster_values;
|
||||
sc.complete_lengths = 1;
|
||||
sc.complete_values = 1;
|
||||
|
||||
if (ngx_http_script_compile(&sc) != NGX_OK) {
|
||||
return NGX_CONF_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_CONF_OK;
|
||||
}
|
||||
|
||||
u_char *ngx_http_nacos_log_handler(ngx_log_t *log, u_char *buf, size_t len) {
|
||||
ngx_http_nacos_peers_t *peers;
|
||||
u_char *p = buf;
|
||||
|
@ -175,12 +293,14 @@ u_char *ngx_http_nacos_log_handler(ngx_log_t *log, u_char *buf, size_t len) {
|
|||
return p;
|
||||
}
|
||||
|
||||
static ngx_http_nacos_peers_t *ngx_http_nacos_create_peers(ngx_log_t *log) {
|
||||
static ngx_http_nacos_peers_t *ngx_http_nacos_create_peers(
|
||||
ngx_log_t *log, ngx_flag_t clustered,
|
||||
ngx_http_upstream_srv_conf_t *origin) {
|
||||
ngx_pool_t *pool;
|
||||
ngx_http_nacos_peers_t *peers;
|
||||
ngx_log_t *new_log;
|
||||
|
||||
pool = ngx_create_pool(1024, log);
|
||||
pool = ngx_create_pool(2048, log);
|
||||
if (pool == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -203,6 +323,8 @@ static ngx_http_nacos_peers_t *ngx_http_nacos_create_peers(ngx_log_t *log) {
|
|||
new_log->handler = ngx_http_nacos_log_handler;
|
||||
new_log->action = "nacos update addrs";
|
||||
|
||||
peers->origin = origin;
|
||||
peers->use_cluster = clustered;
|
||||
peers->pool = pool;
|
||||
peers->ref = 1;
|
||||
if (ngx_array_init(&peers->addrs.addrs, peers->pool, 16,
|
||||
|
@ -213,13 +335,15 @@ static ngx_http_nacos_peers_t *ngx_http_nacos_create_peers(ngx_log_t *log) {
|
|||
return peers;
|
||||
}
|
||||
|
||||
static ngx_int_t ngx_http_nacos_add_server(ngx_http_nacos_peers_t *peers) {
|
||||
static ngx_int_t ngx_http_nacos_add_server(ngx_http_nacos_peers_t *peers,
|
||||
ngx_http_nacos_srv_conf_t *nscf,
|
||||
ngx_pool_t *temp_pool) {
|
||||
ngx_http_upstream_server_t *server;
|
||||
ngx_http_upstream_srv_conf_t *us;
|
||||
ngx_nacos_service_addr_t *adr;
|
||||
ngx_uint_t i, n;
|
||||
ngx_url_t u;
|
||||
us = peers->us;
|
||||
ngx_conf_t cf;
|
||||
|
||||
n = peers->addrs.addrs.nelts;
|
||||
adr = peers->addrs.addrs.elts;
|
||||
|
@ -230,6 +354,12 @@ static ngx_int_t ngx_http_nacos_add_server(ngx_http_nacos_peers_t *peers) {
|
|||
if (ngx_parse_url(peers->pool, &u) != NGX_OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
us = ngx_http_nacos_select_upstream(peers, &adr->cluster);
|
||||
if (us == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
server = ngx_array_push(us->servers);
|
||||
if (server == NULL) {
|
||||
return NGX_ERROR;
|
||||
|
@ -238,7 +368,34 @@ static ngx_int_t ngx_http_nacos_add_server(ngx_http_nacos_peers_t *peers) {
|
|||
server->addrs = u.addrs;
|
||||
server->naddrs = u.naddrs;
|
||||
server->name = u.url;
|
||||
server->weight = adr[i].weight;
|
||||
server->weight =
|
||||
(ngx_uint_t) (adr[i].weight / 0.01 * (double) nscf->weight);
|
||||
server->max_fails = nscf->max_fails;
|
||||
server->fail_timeout = nscf->fail_timeout;
|
||||
}
|
||||
|
||||
if (peers->addrs.addrs.nelts > 0) {
|
||||
if (peers->us) {
|
||||
memset(&cf, 0, sizeof(cf));
|
||||
cf.pool = peers->pool;
|
||||
cf.temp_pool = temp_pool;
|
||||
cf.log = temp_pool->log;
|
||||
if (nscf->original_init_upstream(&cf, peers->us) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
} else {
|
||||
us = peers->clustered_us->elts;
|
||||
n = peers->clustered_us->nelts;
|
||||
for (i = 0; i < n; ++i) {
|
||||
memset(&cf, 0, sizeof(cf));
|
||||
cf.pool = peers->pool;
|
||||
cf.temp_pool = temp_pool;
|
||||
cf.log = temp_pool->log;
|
||||
if (nscf->original_init_upstream(&cf, us + i) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NGX_OK;
|
||||
}
|
||||
|
@ -249,19 +406,15 @@ static ngx_int_t ngx_http_nacos_init_upstream(
|
|||
ngx_pool_t *pool;
|
||||
ngx_http_nacos_peers_t *peers;
|
||||
ngx_http_nacos_srv_conf_t *ncf;
|
||||
ngx_conf_t new_cf;
|
||||
|
||||
ncf = ngx_http_conf_upstream_srv_conf(us, ngx_http_nacos_upstream_module);
|
||||
peers = ngx_http_nacos_create_peers(cf->log);
|
||||
|
||||
peers = ngx_http_nacos_create_peers(cf->log, ncf->cluster.len > 0, us);
|
||||
if (peers == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
pool = peers->pool;
|
||||
if (ngx_http_nacos_create_new_us(peers, us) != NGX_OK) {
|
||||
ngx_destroy_pool(pool);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
sub.key_ptr = &peers->key;
|
||||
sub.data_id = ncf->data_id;
|
||||
|
@ -283,49 +436,89 @@ static ngx_int_t ngx_http_nacos_init_upstream(
|
|||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (ngx_http_nacos_add_server(peers) != NGX_OK) {
|
||||
if (ngx_http_nacos_add_server(peers, ncf, cf->temp_pool) != NGX_OK) {
|
||||
ngx_destroy_pool(pool);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (peers->addrs.addrs.nelts > 0) {
|
||||
new_cf = *cf;
|
||||
new_cf.pool = pool;
|
||||
new_cf.log = pool->log;
|
||||
if (ncf->original_init_upstream(&new_cf, peers->us) != NGX_OK) {
|
||||
ngx_destroy_pool(pool);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
us->peer.init = ngx_http_nacos_init_peers;
|
||||
us->peer.data = peers;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
static ngx_int_t ngx_http_nacos_create_new_us(
|
||||
ngx_http_nacos_peers_t *new_peers, ngx_http_upstream_srv_conf_t *us) {
|
||||
ngx_http_upstream_srv_conf_t *new_us;
|
||||
static ngx_http_upstream_srv_conf_t *ngx_http_nacos_select_upstream(
|
||||
ngx_http_nacos_peers_t *peers, ngx_str_t *cluster) {
|
||||
ngx_http_upstream_srv_conf_t *us;
|
||||
ngx_uint_t i, n;
|
||||
|
||||
new_us = ngx_palloc(new_peers->pool, sizeof(*new_us));
|
||||
if (new_us == NULL) {
|
||||
return NGX_ERROR;
|
||||
if (!peers->use_cluster) {
|
||||
us = peers->us;
|
||||
if (us == NULL) {
|
||||
us = ngx_palloc(peers->pool, sizeof(*us));
|
||||
if (us == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
*new_us = *us;
|
||||
new_us->servers = ngx_array_create(new_peers->pool, 16,
|
||||
*us = *peers->origin;
|
||||
us->servers = ngx_array_create(peers->pool, 16,
|
||||
sizeof(ngx_http_upstream_server_t));
|
||||
if (new_us->servers == NULL) {
|
||||
return NGX_ERROR;
|
||||
if (us->servers == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
new_peers->us = new_us;
|
||||
return NGX_OK;
|
||||
peers->us = us;
|
||||
ngx_str_set(&us->host, "nacos-no-cluster");
|
||||
}
|
||||
} else {
|
||||
if (peers->clustered_us == NULL) {
|
||||
peers->clustered_us = ngx_array_create(peers->pool, 4, sizeof(*us));
|
||||
if (peers->clustered_us == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
us = peers->clustered_us->elts;
|
||||
n = peers->clustered_us->nelts;
|
||||
if (n > 0) {
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (us[i].host.len == cluster->len &&
|
||||
ngx_strncmp(us[i].host.data, cluster->data, cluster->len) ==
|
||||
0) {
|
||||
return us + i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
us = ngx_array_push(peers->clustered_us);
|
||||
if (us == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
*us = *peers->origin;
|
||||
|
||||
us->servers = ngx_array_create(peers->pool, 16,
|
||||
sizeof(ngx_http_upstream_server_t));
|
||||
if (us->servers == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
us->host.len = cluster->len;
|
||||
us->host.data = ngx_palloc(peers->pool, cluster->len + 1);
|
||||
if (us->host.data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ngx_memcpy(us->host.data, cluster->data, cluster->len);
|
||||
us->host.data[cluster->len] = 0;
|
||||
}
|
||||
|
||||
return us;
|
||||
}
|
||||
|
||||
static ngx_int_t ngx_http_nacos_init_peers(ngx_http_request_t *r,
|
||||
ngx_http_upstream_srv_conf_t *us) {
|
||||
ngx_http_nacos_peers_t *peers;
|
||||
ngx_http_nacos_rrp_t *rrp;
|
||||
ngx_http_upstream_srv_conf_t *selected_us, *uc;
|
||||
ngx_str_t cluster;
|
||||
ngx_http_nacos_srv_conf_t *nusf;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t i, n;
|
||||
|
||||
rrp = r->upstream->peer.data;
|
||||
if (rrp == NULL) {
|
||||
|
@ -341,7 +534,42 @@ static ngx_int_t ngx_http_nacos_init_peers(ngx_http_request_t *r,
|
|||
if (peers == NULL || peers->addrs.addrs.nelts == 0) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
rc = peers->us->peer.init(r, peers->us);
|
||||
|
||||
nusf = ngx_http_conf_upstream_srv_conf(us, ngx_http_nacos_upstream_module);
|
||||
|
||||
if (!peers->use_cluster) {
|
||||
selected_us = peers->us;
|
||||
} else {
|
||||
selected_us = NULL;
|
||||
|
||||
ngx_memzero(&cluster, sizeof(cluster));
|
||||
if (nusf->cluster_lengths == NULL) {
|
||||
cluster = nusf->cluster;
|
||||
} else {
|
||||
if (ngx_http_script_run(r, &cluster, nusf->cluster_lengths->elts, 0,
|
||||
nusf->cluster_values->elts) == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
if (peers->clustered_us == NULL || peers->clustered_us->nelts == 0) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
n = peers->clustered_us->nelts;
|
||||
uc = peers->clustered_us->elts;
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (cluster.len == uc[i].host.len &&
|
||||
ngx_strncmp(cluster.data, uc[i].host.data, cluster.len) == 0) {
|
||||
selected_us = uc + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selected_us == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
rc = selected_us->peer.init(r, selected_us);
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
@ -369,7 +597,6 @@ static ngx_http_nacos_peers_t *ngx_http_get_nacos_peers(
|
|||
ngx_http_nacos_peers_t *peers, *new_peers;
|
||||
ngx_http_nacos_srv_conf_t *nusf;
|
||||
ngx_int_t rc;
|
||||
ngx_conf_t cf;
|
||||
|
||||
peers = us->peer.data;
|
||||
|
||||
|
@ -377,7 +604,8 @@ static ngx_http_nacos_peers_t *ngx_http_get_nacos_peers(
|
|||
return peers;
|
||||
}
|
||||
|
||||
new_peers = ngx_http_nacos_create_peers(r->pool->log);
|
||||
new_peers =
|
||||
ngx_http_nacos_create_peers(r->pool->log, peers->use_cluster, us);
|
||||
if (new_peers == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -390,29 +618,12 @@ static ngx_http_nacos_peers_t *ngx_http_get_nacos_peers(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
rc = ngx_http_nacos_create_new_us(new_peers, peers->us);
|
||||
if (rc != NGX_OK) {
|
||||
nusf = ngx_http_conf_upstream_srv_conf(us, ngx_http_nacos_upstream_module);
|
||||
if (ngx_http_nacos_add_server(new_peers, nusf, r->pool) != NGX_OK) {
|
||||
ngx_destroy_pool(new_peers->pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ngx_http_nacos_add_server(new_peers) != NGX_OK) {
|
||||
ngx_destroy_pool(new_peers->pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (new_peers->addrs.addrs.nelts > 0) {
|
||||
memset(&cf, 0, sizeof(cf));
|
||||
cf.pool = new_peers->pool;
|
||||
cf.temp_pool = r->pool;
|
||||
cf.log = r->connection->log;
|
||||
nusf =
|
||||
ngx_http_conf_upstream_srv_conf(us, ngx_http_nacos_upstream_module);
|
||||
if (nusf->original_init_upstream(&cf, new_peers->us) != NGX_OK) {
|
||||
ngx_destroy_pool(new_peers->pool);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
us->peer.data = new_peers;
|
||||
if (--peers->ref == 0) {
|
||||
ngx_destroy_pool(peers->pool);
|
||||
|
|
|
@ -68,6 +68,7 @@ typedef struct {
|
|||
ngx_str_t host;
|
||||
int32_t port;
|
||||
int32_t weight;
|
||||
ngx_str_t cluster;
|
||||
} ngx_nacos_service_addr_t;
|
||||
typedef struct {
|
||||
uint64_t version;
|
||||
|
|
|
@ -103,7 +103,8 @@ ngx_int_t ngx_nacos_write_disk_data(ngx_nacos_main_conf_t *mcf,
|
|||
if (!dir_end) {
|
||||
filename.data[mcf->cache_dir.len] = '/';
|
||||
}
|
||||
fd = ngx_open_file(filename.data, NGX_FILE_WRONLY, NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS);
|
||||
fd = ngx_open_file(filename.data, NGX_FILE_WRONLY, NGX_FILE_TRUNCATE,
|
||||
NGX_FILE_DEFAULT_ACCESS);
|
||||
if (fd == NGX_INVALID_FILE) {
|
||||
err = ngx_errno;
|
||||
ngx_log_error(NGX_LOG_EMERG, pool->log, err,
|
||||
|
@ -429,6 +430,8 @@ static bool ngx_nacos_encode_hosts(pb_ostream_t *stream,
|
|||
instance.host.funcs.encode = ngx_nacos_data_pb_encode_str;
|
||||
instance.port = addr->port;
|
||||
instance.weight = addr->weight;
|
||||
instance.cluster.arg = &addr[i].cluster;
|
||||
instance.cluster.funcs.encode = ngx_nacos_data_pb_encode_str;
|
||||
if (!pb_encode_submessage(stream, Instance_fields, &instance)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -437,11 +440,11 @@ static bool ngx_nacos_encode_hosts(pb_ostream_t *stream,
|
|||
}
|
||||
|
||||
char *ngx_nacos_parse_addrs_from_json(ngx_nacos_resp_json_parser_t *parser) {
|
||||
yajl_val json, arr, item, ip, port, ref, weight, enable, healthy;
|
||||
yajl_val json, arr, item, ip, port, ref, weight, enable, healthy, cluster;
|
||||
size_t i, n;
|
||||
int is;
|
||||
ngx_log_t *log;
|
||||
char *ts, *c;
|
||||
char *ts, *c, *cs;
|
||||
Service service;
|
||||
ngx_nacos_service_addrs_t addrs;
|
||||
ngx_nacos_service_addr_t *addr;
|
||||
|
@ -490,9 +493,11 @@ char *ngx_nacos_parse_addrs_from_json(ngx_nacos_resp_json_parser_t *parser) {
|
|||
}
|
||||
|
||||
ip = yajl_tree_get_field(item, "ip", yajl_t_string);
|
||||
if (!ip) {
|
||||
ngx_log_error(NGX_LOG_WARN, log, 0,
|
||||
"nacos response json hosts ip is not string");
|
||||
cluster = yajl_tree_get_field(item, "clusterName", yajl_t_string);
|
||||
if (!ip || !cluster) {
|
||||
ngx_log_error(
|
||||
NGX_LOG_WARN, log, 0,
|
||||
"nacos response json hosts ip or cluster is not string");
|
||||
return NULL;
|
||||
}
|
||||
port = yajl_tree_get_field(item, "port", yajl_t_number);
|
||||
|
@ -502,6 +507,7 @@ char *ngx_nacos_parse_addrs_from_json(ngx_nacos_resp_json_parser_t *parser) {
|
|||
return NULL;
|
||||
}
|
||||
ts = YAJL_GET_STRING(ip);
|
||||
cs = YAJL_GET_STRING(cluster);
|
||||
is = (int) YAJL_GET_INTEGER(port);
|
||||
|
||||
weight = yajl_tree_get_field(item, "weight", yajl_t_number);
|
||||
|
@ -523,6 +529,8 @@ char *ngx_nacos_parse_addrs_from_json(ngx_nacos_resp_json_parser_t *parser) {
|
|||
}
|
||||
addr->host.data = (u_char *) ts;
|
||||
addr->host.len = strlen(ts);
|
||||
addr->cluster.data = (u_char *) cs;
|
||||
addr->cluster.len = strlen(cs);
|
||||
addr->port = is;
|
||||
addr->weight = (int32_t) w * 100;
|
||||
}
|
||||
|
@ -576,15 +584,20 @@ static bool ngx_nacos_pb_decode_str(pb_istream_t *stream,
|
|||
|
||||
static bool ngx_nacos_decode_instances(pb_istream_t *stream,
|
||||
const pb_field_t *field, void **arg) {
|
||||
struct ngx_pb_decode_ctx_t *ctx;
|
||||
struct ngx_pb_decode_ctx_t *parent;
|
||||
ngx_array_t *addrs;
|
||||
ngx_nacos_service_addr_t *addr;
|
||||
Instance instance;
|
||||
struct ngx_pb_decode_ctx_t host, cluster;
|
||||
|
||||
ctx = *arg;
|
||||
addrs = ctx->arg;
|
||||
instance.host.arg = ctx;
|
||||
parent = *arg;
|
||||
addrs = parent->arg;
|
||||
host.pool = parent->pool;
|
||||
cluster.pool = parent->pool;
|
||||
instance.host.arg = &host;
|
||||
instance.host.funcs.decode = ngx_nacos_pb_decode_str;
|
||||
instance.cluster.arg = &cluster;
|
||||
instance.cluster.funcs.decode = ngx_nacos_pb_decode_str;
|
||||
|
||||
addr = ngx_array_push(addrs);
|
||||
if (addr == NULL) {
|
||||
|
@ -592,13 +605,13 @@ static bool ngx_nacos_decode_instances(pb_istream_t *stream,
|
|||
}
|
||||
instance.port = 0;
|
||||
instance.weight = 0;
|
||||
ctx->arg = &addr->host;
|
||||
host.arg = &addr->host;
|
||||
cluster.arg = &addr->cluster;
|
||||
if (!pb_decode(stream, Instance_fields, &instance)) {
|
||||
return false;
|
||||
}
|
||||
addr->weight = instance.weight;
|
||||
addr->port = instance.port;
|
||||
ctx->arg = addrs;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -182,6 +182,7 @@ struct ngx_nacos_grpc_stream_s {
|
|||
unsigned long_live : 1;
|
||||
unsigned send_buf_block : 1;
|
||||
unsigned send_buf_block_conn : 1;
|
||||
unsigned store_proto_size_buf : 1;
|
||||
};
|
||||
|
||||
#define NGX_NACOS_GRPC_DEFAULT_GRPC_STATUS 10000
|
||||
|
@ -216,16 +217,18 @@ static ngx_int_t ngx_nacos_grpc_send_buf(ngx_nacos_grpc_buf_t *buf,
|
|||
|
||||
static ngx_int_t ngx_nacos_grpc_do_send(ngx_nacos_grpc_stream_t *st);
|
||||
|
||||
#define READ_BUF_CAP 65536
|
||||
// read buf. 128K. max frame
|
||||
#define READ_BUF_CAP (1 << 17)
|
||||
#define MAX_FRAME_SIZE (READ_BUF_CAP - 9)
|
||||
|
||||
static u_char ngx_nacos_grpc_connection_start[] =
|
||||
"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" /* connection preface */
|
||||
|
||||
"\x00\x00\x12\x04\x00\x00\x00\x00\x00" /* settings frame */
|
||||
"\x00\x00\x18\x04\x00\x00\x00\x00\x00" /* settings frame */
|
||||
"\x00\x01\x00\x00\x00\x00" /* header table size */
|
||||
"\x00\x02\x00\x00\x00\x00" /* disable push */
|
||||
"\x00\x04\x7f\xff\xff\xff" /* initial window */
|
||||
|
||||
"\x00\x05\x00\x01\xff\xf7" /* max frame size 128K - 9 */
|
||||
"\x00\x00\x04\x08\x00\x00\x00\x00\x00" /* window update frame */
|
||||
"\x7f\xff\x00\x00";
|
||||
|
||||
|
@ -544,8 +547,14 @@ static void ngx_nacos_grpc_event_handler(ngx_event_t *ev) {
|
|||
gc = c->data;
|
||||
if (ev == c->read) {
|
||||
rc = ngx_nacos_grpc_read_handler(gc, ev);
|
||||
if (rc == NGX_AGAIN && ngx_handle_read_event(ev, 0) != NGX_OK) {
|
||||
rc = NGX_ERROR;
|
||||
}
|
||||
} else {
|
||||
rc = ngx_nacos_grpc_write_handler(gc, ev);
|
||||
if (rc == NGX_AGAIN && ngx_handle_write_event(ev, 0) != NGX_OK) {
|
||||
rc = NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == NGX_ERROR || rc == NGX_DONE) {
|
||||
|
@ -654,7 +663,7 @@ static ngx_int_t ngx_nacos_grpc_read_handler(ngx_nacos_grpc_conn_t *gc,
|
|||
} else if (rc == 0) {
|
||||
return NGX_DONE;
|
||||
} else if (rc == NGX_AGAIN) {
|
||||
return NGX_OK;
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -672,7 +681,7 @@ static ngx_int_t ngx_nacos_grpc_parse_frame(ngx_nacos_grpc_conn_t *gc) {
|
|||
|
||||
if (gc->parse_stat == parse_frame_header) {
|
||||
if (len < 9) {
|
||||
return NGX_AGAIN;
|
||||
break;
|
||||
}
|
||||
gc->frame_size =
|
||||
(((size_t) b->pos[0]) << 16) | (b->pos[1] << 8) | (b->pos[2]);
|
||||
|
@ -684,43 +693,55 @@ static ngx_int_t ngx_nacos_grpc_parse_frame(ngx_nacos_grpc_conn_t *gc) {
|
|||
gc->parse_stat = parse_frame_payload;
|
||||
b->pos += 9;
|
||||
gc->frame_start = 1;
|
||||
gc->frame_end = len - 9 >= gc->frame_size ? 1 : 0;
|
||||
len -= 9;
|
||||
|
||||
if (gc->frame_type >
|
||||
sizeof(frame_handlers) / sizeof(ngx_nacos_grpc_frame_handler)) {
|
||||
ngx_log_error(NGX_LOG_ERR, gc->conn->log, 0,
|
||||
"nacos http2 protocol error. error frame type");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (gc->frame_size > MAX_FRAME_SIZE) {
|
||||
ngx_log_error(
|
||||
NGX_LOG_ERR, gc->conn->log, 0,
|
||||
"nacos http2 protocol error. exceed max frame size");
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (gc->parse_stat == parse_frame_payload) {
|
||||
if (gc->frame_type >
|
||||
sizeof(frame_handlers) / sizeof(ngx_nacos_grpc_frame_handler)) {
|
||||
return NGX_ERROR;
|
||||
gc->frame_end = len >= gc->frame_size ? 1 : 0;
|
||||
if (!gc->frame_end) {
|
||||
break;
|
||||
}
|
||||
pp = b->pos;
|
||||
|
||||
lp = b->last;
|
||||
if ((size_t) (lp - pp) > gc->frame_size) {
|
||||
b->last = pp + gc->frame_size;
|
||||
if ((size_t) (lp - b->pos) > gc->frame_size) {
|
||||
b->last = b->pos + gc->frame_size;
|
||||
}
|
||||
pp = b->last;
|
||||
rc = frame_handlers[gc->frame_type](gc);
|
||||
if (b->pos == b->last) {
|
||||
gc->parse_stat = parse_frame_header;
|
||||
} else if (b->pos != pp) {
|
||||
gc->frame_start = 0;
|
||||
}
|
||||
b->pos = pp;
|
||||
b->last = lp;
|
||||
if (rc == NGX_ERROR || rc == NGX_DONE) {
|
||||
|
||||
if (rc != NGX_OK) {
|
||||
return rc;
|
||||
} else if (rc == NGX_AGAIN) {
|
||||
}
|
||||
gc->parse_stat = parse_frame_header;
|
||||
}
|
||||
}
|
||||
|
||||
len = b->last - b->pos;
|
||||
if (len > 0 && len * 4 < (size_t) (b->end - b->start) &&
|
||||
(size_t) (b->end - b->pos) * 2 <
|
||||
(size_t) (b->end - b->start)) {
|
||||
if (len == 0) {
|
||||
b->pos = b->last = b->start;
|
||||
} else if (len > 0 && len * 4 < (size_t) (b->end - b->start) &&
|
||||
(size_t) (b->end - b->pos) * 2 < (size_t) (b->end - b->start)) {
|
||||
ngx_memcpy(b->start, b->pos, len);
|
||||
b->pos = b->start;
|
||||
b->last = b->pos + len;
|
||||
} else if (len == 0) {
|
||||
b->pos = b->last = b->start;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NGX_AGAIN;
|
||||
}
|
||||
|
||||
static ngx_nacos_grpc_stream_t *ngx_nacos_grpc_create_stream(
|
||||
|
@ -977,7 +998,7 @@ static ngx_int_t ngx_nacos_grpc_parse_unknown_frame(ngx_nacos_grpc_conn_t *gc) {
|
|||
static ngx_int_t ngx_nacos_grpc_parse_data_frame(ngx_nacos_grpc_conn_t *gc) {
|
||||
ngx_nacos_grpc_stream_t *st;
|
||||
ngx_buf_t *buf, *tb;
|
||||
u_char *p;
|
||||
u_char *p, *t;
|
||||
ngx_int_t rc;
|
||||
size_t len, msg_size;
|
||||
ngx_str_t proto_msg;
|
||||
|
@ -1008,6 +1029,11 @@ static ngx_int_t ngx_nacos_grpc_parse_data_frame(ngx_nacos_grpc_conn_t *gc) {
|
|||
p = buf->pos;
|
||||
len = buf->last - p;
|
||||
|
||||
if (len == 0) {
|
||||
rc = NGX_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
if (gc->frame_start) {
|
||||
if (gc->frame_flags & HTTP_V2_PADDED_FLAG) {
|
||||
if (len < 1) {
|
||||
|
@ -1023,11 +1049,48 @@ static ngx_int_t ngx_nacos_grpc_parse_data_frame(ngx_nacos_grpc_conn_t *gc) {
|
|||
}
|
||||
|
||||
if (st->parsing_state == parsing_prefix) {
|
||||
if (len < 5) {
|
||||
if (st->store_proto_size_buf) {
|
||||
tb = st->tmp_buf;
|
||||
if (len > 5 - (size_t) (tb->last - tb->pos)) {
|
||||
msg_size = 5 - (tb->last - tb->pos);
|
||||
} else {
|
||||
msg_size = len;
|
||||
}
|
||||
memcpy(tb->last, p, msg_size);
|
||||
tb->last += msg_size;
|
||||
p += msg_size;
|
||||
buf->pos = p;
|
||||
if (tb->last - tb->pos < 5) {
|
||||
rc = NGX_OK;
|
||||
break;
|
||||
}
|
||||
if (p[0] != 0) {
|
||||
} else if (len < 5) {
|
||||
if (ngx_nacos_grpc_realloc_tmp_buf(st, 256) != NGX_OK) {
|
||||
rc = NGX_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
tb = st->tmp_buf;
|
||||
memcpy(tb->last, p, len);
|
||||
tb->last += len;
|
||||
p += len;
|
||||
buf->pos = p;
|
||||
rc = NGX_OK;
|
||||
st->store_proto_size_buf = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (st->store_proto_size_buf) {
|
||||
t = tb->pos;
|
||||
tb->pos = tb->last = tb->start;
|
||||
} else {
|
||||
t = p;
|
||||
p += 5;
|
||||
len -= 5;
|
||||
buf->pos = p;
|
||||
}
|
||||
|
||||
if (t[0] != 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, gc->conn->log, 0,
|
||||
"nacos server sent data frame "
|
||||
"send compressed msg: %uz",
|
||||
|
@ -1035,15 +1098,13 @@ static ngx_int_t ngx_nacos_grpc_parse_data_frame(ngx_nacos_grpc_conn_t *gc) {
|
|||
rc = NGX_ERROR;
|
||||
break;
|
||||
}
|
||||
msg_size = (p[1] << 24) | (p[2] << 16) | (p[3] << 8) | p[4];
|
||||
msg_size = (t[1] << 24) | (t[2] << 16) | (t[3] << 8) | t[4];
|
||||
|
||||
if (ngx_nacos_grpc_realloc_tmp_buf(st, msg_size) != NGX_OK) {
|
||||
rc = NGX_ERROR;
|
||||
break;
|
||||
}
|
||||
tb = st->tmp_buf;
|
||||
p += 5;
|
||||
len -= 5;
|
||||
buf->pos = p;
|
||||
st->parsing_state = parsing_msg;
|
||||
st->proto_len = msg_size;
|
||||
st->recv_win -= 5;
|
||||
|
@ -1063,6 +1124,9 @@ static ngx_int_t ngx_nacos_grpc_parse_data_frame(ngx_nacos_grpc_conn_t *gc) {
|
|||
st->padding = 0;
|
||||
}
|
||||
len = tb->last - tb->pos;
|
||||
if (st->proto_len > 300000) {
|
||||
st->padding = 0;
|
||||
}
|
||||
if (len == st->proto_len) {
|
||||
proto_msg.len = len;
|
||||
proto_msg.data = tb->pos;
|
||||
|
@ -1223,8 +1287,7 @@ static ngx_int_t ngx_nacos_grpc_parse_header_frame(ngx_nacos_grpc_conn_t *gc) {
|
|||
b->pos = p;
|
||||
len = b->last - p;
|
||||
gc->frame_size -= min;
|
||||
gc->frame_flags &=
|
||||
~(HTTP_V2_PADDED_FLAG | HTTP_V2_PRIORITY_FLAG);
|
||||
gc->frame_flags &= ~(HTTP_V2_PADDED_FLAG | HTTP_V2_PRIORITY_FLAG);
|
||||
st->parsing_state = p_receiving;
|
||||
}
|
||||
}
|
||||
|
@ -1372,7 +1435,8 @@ parse_header:
|
|||
ch = 0;
|
||||
tp = tmp;
|
||||
if (ngx_nacos_http_v2_huff_decode(&ch, p, field_len, &tp, 1,
|
||||
gc->conn->log) != NGX_OK) {
|
||||
gc->conn->log) !=
|
||||
NGX_OK) {
|
||||
ngx_log_error(
|
||||
NGX_LOG_ERR, gc->conn->log, 0,
|
||||
"nacos server sent invalid encoded header");
|
||||
|
@ -1421,7 +1485,8 @@ parse_header:
|
|||
ch = 0;
|
||||
tp = tmp;
|
||||
if (ngx_nacos_http_v2_huff_decode(&ch, p, field_len, &tp, 1,
|
||||
gc->conn->log) != NGX_OK) {
|
||||
gc->conn->log) !=
|
||||
NGX_OK) {
|
||||
ngx_log_error(
|
||||
NGX_LOG_ERR, gc->conn->log, 0,
|
||||
"nacos server sent invalid encoded header");
|
||||
|
@ -1634,8 +1699,8 @@ static ngx_int_t ngx_nacos_grpc_parse_ping_frame(ngx_nacos_grpc_conn_t *gc) {
|
|||
if (buf == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
ngx_nacos_grpc_encode_frame_header(
|
||||
gc->m_stream, buf->b, HTTP_V2_PING_FRAME, HTTP_V2_ACK_FLAG, 8);
|
||||
ngx_nacos_grpc_encode_frame_header(gc->m_stream, buf->b, HTTP_V2_PING_FRAME,
|
||||
HTTP_V2_ACK_FLAG, 8);
|
||||
buf->len = 9 + 8;
|
||||
p = buf->b + 9;
|
||||
p[0] = (data >> 56) & 0xFF;
|
||||
|
@ -1849,7 +1914,8 @@ static ngx_nacos_grpc_buf_t *ngx_nacos_grpc_encode_request(
|
|||
// user-agent
|
||||
*b++ = ngx_nacos_http_v2_inc_indexed(HTTP_V2_USER_AGENT_INDEX);
|
||||
b = ngx_nacos_http_v2_write_value(b, (u_char *) "nginx-nacos-grpc-client",
|
||||
sizeof("nginx-nacos-grpc-client") - 1, tmp);
|
||||
sizeof("nginx-nacos-grpc-client") - 1,
|
||||
tmp);
|
||||
// content-type
|
||||
*b++ = ngx_nacos_http_v2_inc_indexed(HTTP_V2_CONTENT_TYPE_INDEX);
|
||||
b = ngx_nacos_http_v2_write_value(b, (u_char *) "application/grpc",
|
||||
|
@ -2241,6 +2307,8 @@ static ngx_int_t ngx_nacos_grpc_encode_payload_init(
|
|||
en->payload.body.value.funcs.encode = ngx_nacos_grpc_pb_encode_str;
|
||||
en->payload.metadata.type.arg = &en->type;
|
||||
en->payload.metadata.type.funcs.encode = ngx_nacos_grpc_pb_encode_str;
|
||||
en->payload.has_metadata = 1;
|
||||
en->payload.has_body = 1;
|
||||
|
||||
if (grpc_ctx.ncf->username.len > 0 && grpc_ctx.ncf->password.len > 0) {
|
||||
en->payload.metadata.headers.arg = grpc_ctx.ncf;
|
||||
|
@ -2292,9 +2360,9 @@ static ngx_nacos_grpc_buf_t *ngx_nacos_grpc_encode_data_msg(
|
|||
goto err;
|
||||
}
|
||||
b = buf->b;
|
||||
ngx_nacos_grpc_encode_frame_header(
|
||||
st, b, HTTP_V2_DATA_FRAME,
|
||||
end_stream ? HTTP_V2_END_STREAM_FLAG : 0, 5 + b_len);
|
||||
ngx_nacos_grpc_encode_frame_header(st, b, HTTP_V2_DATA_FRAME,
|
||||
end_stream ? HTTP_V2_END_STREAM_FLAG : 0,
|
||||
5 + b_len);
|
||||
b[9] = 0;
|
||||
b[10] = (b_len >> 24) & 0xFF;
|
||||
b[11] = (b_len >> 16) & 0xFF;
|
||||
|
@ -2468,8 +2536,8 @@ static ngx_int_t ngx_nacos_grpc_send_win_update_frame(
|
|||
if (buf == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
ngx_nacos_grpc_encode_frame_header(st, buf->b,
|
||||
HTTP_V2_WINDOW_UPDATE_FRAME, 0, 4);
|
||||
ngx_nacos_grpc_encode_frame_header(st, buf->b, HTTP_V2_WINDOW_UPDATE_FRAME,
|
||||
0, 4);
|
||||
buf->len = 9 + 4;
|
||||
p = buf->b + 9;
|
||||
p[0] = (win_update >> 24) & 0x7F;
|
||||
|
@ -2492,8 +2560,8 @@ static ngx_int_t ngx_nacos_send_ping_frame(ngx_nacos_grpc_conn_t *gc) {
|
|||
if (buf == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
ngx_nacos_grpc_encode_frame_header(gc->m_stream, buf->b,
|
||||
HTTP_V2_PING_FRAME, 0, 8);
|
||||
ngx_nacos_grpc_encode_frame_header(gc->m_stream, buf->b, HTTP_V2_PING_FRAME,
|
||||
0, 8);
|
||||
p = buf->b + 9;
|
||||
data = ++gc->heartbeat;
|
||||
p[0] = (data >> 56) & 0xFF;
|
||||
|
|
|
@ -14,16 +14,14 @@
|
|||
/* #define PB_ENABLE_MALLOC 1 */
|
||||
|
||||
/* Define this if your CPU / compiler combination does not support
|
||||
* unaligned memory access to packed structures. */
|
||||
* unaligned memory access to packed structures. Note that packed
|
||||
* structures are only used when requested in .proto options. */
|
||||
/* #define PB_NO_PACKED_STRUCTS 1 */
|
||||
|
||||
/* Increase the number of required fields that are tracked.
|
||||
* A compiler warning will tell if you need this. */
|
||||
/* #define PB_MAX_REQUIRED_FIELDS 256 */
|
||||
|
||||
/* Add support for tag numbers > 255 and fields larger than 255 bytes. */
|
||||
/* #define PB_FIELD_16BIT 1 */
|
||||
|
||||
/* Add support for tag numbers > 65536 and fields larger than 65536 bytes. */
|
||||
/* #define PB_FIELD_32BIT 1 */
|
||||
|
||||
|
@ -33,16 +31,32 @@
|
|||
/* Disable support for custom streams (support only memory buffers). */
|
||||
/* #define PB_BUFFER_ONLY 1 */
|
||||
|
||||
/* Switch back to the old-style callback function signature.
|
||||
* This was the default until nanopb-0.2.1. */
|
||||
/* #define PB_OLD_CALLBACK_STYLE */
|
||||
|
||||
/* Disable support for 64-bit datatypes, for compilers without int64_t
|
||||
or to save some code space. */
|
||||
/* #define PB_WITHOUT_64BIT 1 */
|
||||
|
||||
/* Don't encode scalar arrays as packed. This is only to be used when
|
||||
* the decoder on the receiving side cannot process packed scalar arrays.
|
||||
* Such example is older protobuf.js. */
|
||||
/* #define PB_ENCODE_ARRAYS_UNPACKED 1 */
|
||||
|
||||
/* Enable conversion of doubles to floats for platforms that do not
|
||||
* support 64-bit doubles. Most commonly AVR. */
|
||||
/* #define PB_CONVERT_DOUBLE_FLOAT 1 */
|
||||
|
||||
/* Check whether incoming strings are valid UTF-8 sequences. Slows down
|
||||
* the string processing slightly and slightly increases code size. */
|
||||
/* #define PB_VALIDATE_UTF8 1 */
|
||||
|
||||
/* This can be defined if the platform is little-endian and has 8-bit bytes.
|
||||
* Normally it is automatically detected based on __BYTE_ORDER__ macro. */
|
||||
/* #define PB_LITTLE_ENDIAN_8BIT 1 */
|
||||
|
||||
/* Configure static assert mechanism. Instead of changing these, set your
|
||||
* compiler to C11 standard mode if possible. */
|
||||
/* #define PB_C99_STATIC_ASSERT 1 */
|
||||
/* #define PB_NO_STATIC_ASSERT 1 */
|
||||
|
||||
/******************************************************************
|
||||
* You usually don't need to change anything below this line. *
|
||||
* Feel free to look around and use the defined macros, though. *
|
||||
|
@ -51,7 +65,7 @@
|
|||
|
||||
/* Version of the nanopb library. Just in case you want to check it in
|
||||
* your own program. */
|
||||
#define NANOPB_VERSION nanopb-0.3.9.10
|
||||
#define NANOPB_VERSION "nanopb-0.4.9"
|
||||
|
||||
/* Include all the system headers needed by nanopb. You will need the
|
||||
* definitions of the following:
|
||||
|
@ -72,12 +86,17 @@
|
|||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <ngx_auto_headers.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Macro for defining packed structures (compiler dependent).
|
||||
* This just reduces memory requirements, but is not required.
|
||||
*/
|
||||
|
@ -108,11 +127,36 @@
|
|||
# define pb_packed
|
||||
#endif
|
||||
|
||||
/* Detect endianness */
|
||||
#ifndef PB_LITTLE_ENDIAN_8BIT
|
||||
#if ((defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
|
||||
defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || \
|
||||
defined(__THUMBEL__) || defined(__AARCH64EL__) || defined(_MIPSEL) || \
|
||||
defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM)) \
|
||||
&& CHAR_BIT == 8
|
||||
#define PB_LITTLE_ENDIAN_8BIT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Handly macro for suppressing unreferenced-parameter compiler warnings. */
|
||||
#ifndef PB_UNUSED
|
||||
#define PB_UNUSED(x) (void)(x)
|
||||
#endif
|
||||
|
||||
/* Harvard-architecture processors may need special attributes for storing
|
||||
* field information in program memory. */
|
||||
#ifndef PB_PROGMEM
|
||||
#ifdef __AVR__
|
||||
#include <avr/pgmspace.h>
|
||||
#define PB_PROGMEM PROGMEM
|
||||
#define PB_PROGMEM_READU32(x) pgm_read_dword(&x)
|
||||
#else
|
||||
#define PB_PROGMEM
|
||||
#define PB_PROGMEM_READU32(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Compile-time assertion, used for checking compatible compilation options.
|
||||
* If this does not work properly on your compiler, use
|
||||
* #define PB_NO_STATIC_ASSERT to disable it.
|
||||
|
@ -124,14 +168,38 @@
|
|||
*/
|
||||
#ifndef PB_NO_STATIC_ASSERT
|
||||
# ifndef PB_STATIC_ASSERT
|
||||
# if defined(__ICCARM__)
|
||||
/* IAR has static_assert keyword but no _Static_assert */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) static_assert(COND,#MSG);
|
||||
# elif defined(_MSC_VER) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112)
|
||||
/* MSVC in C89 mode supports static_assert() keyword anyway */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) static_assert(COND,#MSG);
|
||||
# elif defined(PB_C99_STATIC_ASSERT)
|
||||
/* Classic negative-size-array static assert mechanism */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) typedef char PB_STATIC_ASSERT_MSG(MSG, __LINE__, __COUNTER__)[(COND)?1:-1];
|
||||
# define PB_STATIC_ASSERT_MSG(MSG, LINE, COUNTER) PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER)
|
||||
#define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##LINE##COUNTER
|
||||
# define PB_STATIC_ASSERT_MSG_(MSG, LINE, COUNTER) pb_static_assertion_##MSG##_##LINE##_##COUNTER
|
||||
# elif defined(__cplusplus)
|
||||
/* C++11 standard static_assert mechanism */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) static_assert(COND,#MSG);
|
||||
# else
|
||||
/* C11 standard _Static_assert mechanism */
|
||||
# define PB_STATIC_ASSERT(COND,MSG) _Static_assert(COND,#MSG);
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
/* Static asserts disabled by PB_NO_STATIC_ASSERT */
|
||||
# define PB_STATIC_ASSERT(COND,MSG)
|
||||
#endif
|
||||
|
||||
/* Test that PB_STATIC_ASSERT works
|
||||
* If you get errors here, you may need to do one of these:
|
||||
* - Enable C11 standard support in your compiler
|
||||
* - Define PB_C99_STATIC_ASSERT to enable C99 standard support
|
||||
* - Define PB_NO_STATIC_ASSERT to disable static asserts altogether
|
||||
*/
|
||||
PB_STATIC_ASSERT(1, STATIC_ASSERT_IS_NOT_WORKING)
|
||||
|
||||
/* Number of required fields to keep track of. */
|
||||
#ifndef PB_MAX_REQUIRED_FIELDS
|
||||
#define PB_MAX_REQUIRED_FIELDS 64
|
||||
|
@ -141,70 +209,97 @@
|
|||
#error You should not lower PB_MAX_REQUIRED_FIELDS from the default value (64).
|
||||
#endif
|
||||
|
||||
#ifdef PB_WITHOUT_64BIT
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
/* Cannot use doubles without 64-bit types */
|
||||
#undef PB_CONVERT_DOUBLE_FLOAT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Data type for storing encoded data and other byte streams.
|
||||
* This typedef exists to support platforms where uint8_t does not exist.
|
||||
* You can regard it as equivalent on uint8_t on other platforms.
|
||||
*/
|
||||
#if defined(PB_BYTE_T_OVERRIDE)
|
||||
typedef PB_BYTE_T_OVERRIDE pb_byte_t;
|
||||
#elif defined(UINT8_MAX)
|
||||
typedef uint8_t pb_byte_t;
|
||||
#else
|
||||
typedef uint_least8_t pb_byte_t;
|
||||
#endif
|
||||
|
||||
/* List of possible field types. These are used in the autogenerated code.
|
||||
* Least-significant 4 bits tell the scalar type
|
||||
* Most-significant 4 bits specify repeated/required/packed etc.
|
||||
*/
|
||||
|
||||
typedef uint_least8_t pb_type_t;
|
||||
typedef pb_byte_t pb_type_t;
|
||||
|
||||
/**** Field data types ****/
|
||||
|
||||
/* Numeric types */
|
||||
#define PB_LTYPE_BOOL 0x00 /* bool */
|
||||
#define PB_LTYPE_VARINT 0x01 /* int32, int64, enum, bool */
|
||||
#define PB_LTYPE_UVARINT 0x02 /* uint32, uint64 */
|
||||
#define PB_LTYPE_SVARINT 0x03 /* sint32, sint64 */
|
||||
#define PB_LTYPE_FIXED32 0x04 /* fixed32, sfixed32, float */
|
||||
#define PB_LTYPE_FIXED64 0x05 /* fixed64, sfixed64, double */
|
||||
#define PB_LTYPE_BOOL 0x00U /* bool */
|
||||
#define PB_LTYPE_VARINT 0x01U /* int32, int64, enum, bool */
|
||||
#define PB_LTYPE_UVARINT 0x02U /* uint32, uint64 */
|
||||
#define PB_LTYPE_SVARINT 0x03U /* sint32, sint64 */
|
||||
#define PB_LTYPE_FIXED32 0x04U /* fixed32, sfixed32, float */
|
||||
#define PB_LTYPE_FIXED64 0x05U /* fixed64, sfixed64, double */
|
||||
|
||||
/* Marker for last packable field type. */
|
||||
#define PB_LTYPE_LAST_PACKABLE 0x05
|
||||
#define PB_LTYPE_LAST_PACKABLE 0x05U
|
||||
|
||||
/* Byte array with pre-allocated buffer.
|
||||
* data_size is the length of the allocated PB_BYTES_ARRAY structure. */
|
||||
#define PB_LTYPE_BYTES 0x06
|
||||
#define PB_LTYPE_BYTES 0x06U
|
||||
|
||||
/* String with pre-allocated buffer.
|
||||
* data_size is the maximum length. */
|
||||
#define PB_LTYPE_STRING 0x07
|
||||
#define PB_LTYPE_STRING 0x07U
|
||||
|
||||
/* Submessage
|
||||
* submsg_fields is pointer to field descriptions */
|
||||
#define PB_LTYPE_SUBMESSAGE 0x08
|
||||
#define PB_LTYPE_SUBMESSAGE 0x08U
|
||||
|
||||
/* Submessage with pre-decoding callback
|
||||
* The pre-decoding callback is stored as pb_callback_t right before pSize.
|
||||
* submsg_fields is pointer to field descriptions */
|
||||
#define PB_LTYPE_SUBMSG_W_CB 0x09U
|
||||
|
||||
/* Extension pseudo-field
|
||||
* The field contains a pointer to pb_extension_t */
|
||||
#define PB_LTYPE_EXTENSION 0x09
|
||||
#define PB_LTYPE_EXTENSION 0x0AU
|
||||
|
||||
/* Byte array with inline, pre-allocated byffer.
|
||||
* data_size is the length of the inline, allocated buffer.
|
||||
* This differs from PB_LTYPE_BYTES by defining the element as
|
||||
* pb_byte_t[data_size] rather than pb_bytes_array_t. */
|
||||
#define PB_LTYPE_FIXED_LENGTH_BYTES 0x0A
|
||||
#define PB_LTYPE_FIXED_LENGTH_BYTES 0x0BU
|
||||
|
||||
/* Number of declared LTYPES */
|
||||
#define PB_LTYPES_COUNT 0x0B
|
||||
#define PB_LTYPE_MASK 0x0F
|
||||
#define PB_LTYPES_COUNT 0x0CU
|
||||
#define PB_LTYPE_MASK 0x0FU
|
||||
|
||||
/**** Field repetition rules ****/
|
||||
|
||||
#define PB_HTYPE_REQUIRED 0x00
|
||||
#define PB_HTYPE_OPTIONAL 0x10
|
||||
#define PB_HTYPE_REPEATED 0x20
|
||||
#define PB_HTYPE_ONEOF 0x30
|
||||
#define PB_HTYPE_MASK 0x30
|
||||
#define PB_HTYPE_REQUIRED 0x00U
|
||||
#define PB_HTYPE_OPTIONAL 0x10U
|
||||
#define PB_HTYPE_SINGULAR 0x10U
|
||||
#define PB_HTYPE_REPEATED 0x20U
|
||||
#define PB_HTYPE_FIXARRAY 0x20U
|
||||
#define PB_HTYPE_ONEOF 0x30U
|
||||
#define PB_HTYPE_MASK 0x30U
|
||||
|
||||
/**** Field allocation types ****/
|
||||
|
||||
#define PB_ATYPE_STATIC 0x00
|
||||
#define PB_ATYPE_POINTER 0x80
|
||||
#define PB_ATYPE_CALLBACK 0x40
|
||||
#define PB_ATYPE_MASK 0xC0
|
||||
#define PB_ATYPE_STATIC 0x00U
|
||||
#define PB_ATYPE_POINTER 0x80U
|
||||
#define PB_ATYPE_CALLBACK 0x40U
|
||||
#define PB_ATYPE_MASK 0xC0U
|
||||
|
||||
#define PB_ATYPE(x) ((x) & PB_ATYPE_MASK)
|
||||
#define PB_HTYPE(x) ((x) & PB_HTYPE_MASK)
|
||||
#define PB_LTYPE(x) ((x) & PB_LTYPE_MASK)
|
||||
#define PB_LTYPE_IS_SUBMSG(x) (PB_LTYPE(x) == PB_LTYPE_SUBMESSAGE || \
|
||||
PB_LTYPE(x) == PB_LTYPE_SUBMSG_W_CB)
|
||||
|
||||
/* Data type used for storing sizes of struct fields
|
||||
* and array counts.
|
||||
|
@ -212,45 +307,57 @@ typedef uint_least8_t pb_type_t;
|
|||
#if defined(PB_FIELD_32BIT)
|
||||
typedef uint32_t pb_size_t;
|
||||
typedef int32_t pb_ssize_t;
|
||||
#elif defined(PB_FIELD_16BIT)
|
||||
#else
|
||||
typedef uint_least16_t pb_size_t;
|
||||
typedef int_least16_t pb_ssize_t;
|
||||
#else
|
||||
typedef uint_least8_t pb_size_t;
|
||||
typedef int_least8_t pb_ssize_t;
|
||||
#endif
|
||||
#define PB_SIZE_MAX ((pb_size_t)-1)
|
||||
|
||||
/* Data type for storing encoded data and other byte streams.
|
||||
* This typedef exists to support platforms where uint8_t does not exist.
|
||||
* You can regard it as equivalent on uint8_t on other platforms.
|
||||
*/
|
||||
typedef uint_least8_t pb_byte_t;
|
||||
/* Forward declaration of struct types */
|
||||
typedef struct pb_istream_s pb_istream_t;
|
||||
typedef struct pb_ostream_s pb_ostream_t;
|
||||
typedef struct pb_field_iter_s pb_field_iter_t;
|
||||
|
||||
/* This structure is used in auto-generated constants
|
||||
* to specify struct fields.
|
||||
* You can change field sizes if you need structures
|
||||
* larger than 256 bytes or field tags larger than 256.
|
||||
* The compiler should complain if your .proto has such
|
||||
* structures. Fix that by defining PB_FIELD_16BIT or
|
||||
* PB_FIELD_32BIT.
|
||||
*/
|
||||
PB_PACKED_STRUCT_START
|
||||
typedef struct pb_field_s pb_field_t;
|
||||
struct pb_field_s {
|
||||
pb_size_t tag;
|
||||
pb_type_t type;
|
||||
pb_size_t data_offset; /* Offset of field data, relative to previous field. */
|
||||
pb_ssize_t size_offset; /* Offset of array size or has-boolean, relative to data */
|
||||
pb_size_t data_size; /* Data size in bytes for a single item */
|
||||
pb_size_t array_size; /* Maximum number of entries in array */
|
||||
typedef struct pb_msgdesc_s pb_msgdesc_t;
|
||||
struct pb_msgdesc_s {
|
||||
const uint32_t *field_info;
|
||||
const pb_msgdesc_t * const * submsg_info;
|
||||
const pb_byte_t *default_value;
|
||||
|
||||
/* Field definitions for submessage
|
||||
* OR default value for all other non-array, non-callback types
|
||||
* If null, then field will zeroed. */
|
||||
const void *ptr;
|
||||
} pb_packed;
|
||||
PB_PACKED_STRUCT_END
|
||||
bool (*field_callback)(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field);
|
||||
|
||||
pb_size_t field_count;
|
||||
pb_size_t required_field_count;
|
||||
pb_size_t largest_tag;
|
||||
};
|
||||
|
||||
/* Iterator for message descriptor */
|
||||
struct pb_field_iter_s {
|
||||
const pb_msgdesc_t *descriptor; /* Pointer to message descriptor constant */
|
||||
void *message; /* Pointer to start of the structure */
|
||||
|
||||
pb_size_t index; /* Index of the field */
|
||||
pb_size_t field_info_index; /* Index to descriptor->field_info array */
|
||||
pb_size_t required_field_index; /* Index that counts only the required fields */
|
||||
pb_size_t submessage_index; /* Index that counts only submessages */
|
||||
|
||||
pb_size_t tag; /* Tag of current field */
|
||||
pb_size_t data_size; /* sizeof() of a single item */
|
||||
pb_size_t array_size; /* Number of array entries */
|
||||
pb_type_t type; /* Type of current field */
|
||||
|
||||
void *pField; /* Pointer to current field in struct */
|
||||
void *pData; /* Pointer to current data contents. Different than pField for arrays and pointers. */
|
||||
void *pSize; /* Pointer to count/has field */
|
||||
|
||||
const pb_msgdesc_t *submsg_desc; /* For submessage fields, pointer to field descriptor for the submessage. */
|
||||
};
|
||||
|
||||
/* For compatibility with legacy code */
|
||||
typedef pb_field_iter_t pb_field_t;
|
||||
|
||||
/* Make sure that the standard integer types are of the expected sizes.
|
||||
* Otherwise fixed32/fixed64 fields can break.
|
||||
|
@ -294,34 +401,29 @@ typedef struct pb_bytes_array_s pb_bytes_array_t;
|
|||
*
|
||||
* The callback can be null if you want to skip a field.
|
||||
*/
|
||||
typedef struct pb_istream_s pb_istream_t;
|
||||
typedef struct pb_ostream_s pb_ostream_t;
|
||||
typedef struct pb_callback_s pb_callback_t;
|
||||
struct pb_callback_s {
|
||||
#ifdef PB_OLD_CALLBACK_STYLE
|
||||
/* Deprecated since nanopb-0.2.1 */
|
||||
union {
|
||||
bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void *arg);
|
||||
bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, const void *arg);
|
||||
} funcs;
|
||||
#else
|
||||
/* New function signature, which allows modifying arg contents in callback. */
|
||||
/* Callback functions receive a pointer to the arg field.
|
||||
* You can access the value of the field as *arg, and modify it if needed.
|
||||
*/
|
||||
union {
|
||||
bool (*decode)(pb_istream_t *stream, const pb_field_t *field, void **arg);
|
||||
bool (*encode)(pb_ostream_t *stream, const pb_field_t *field, void * const *arg);
|
||||
} funcs;
|
||||
#endif
|
||||
|
||||
/* Free arg for use by callback */
|
||||
void *arg;
|
||||
};
|
||||
|
||||
extern bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field);
|
||||
|
||||
/* Wire types. Library user needs these only in encoder callbacks. */
|
||||
typedef enum {
|
||||
PB_WT_VARINT = 0,
|
||||
PB_WT_64BIT = 1,
|
||||
PB_WT_STRING = 2,
|
||||
PB_WT_32BIT = 5
|
||||
PB_WT_32BIT = 5,
|
||||
PB_WT_PACKED = 255 /* PB_WT_PACKED is internal marker for packed arrays. */
|
||||
} pb_wire_type_t;
|
||||
|
||||
/* Structure for defining the handling of unknown/extension fields.
|
||||
|
@ -373,6 +475,8 @@ struct pb_extension_s {
|
|||
bool found;
|
||||
};
|
||||
|
||||
#define pb_extension_init_zero {NULL,NULL,NULL,false}
|
||||
|
||||
/* Memory allocation functions to use. You can define pb_realloc and
|
||||
* pb_free to custom functions if you want. */
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
|
@ -385,7 +489,7 @@ struct pb_extension_s {
|
|||
#endif
|
||||
|
||||
/* This is used to inform about need to regenerate .pb.h/.pb.c files. */
|
||||
#define PB_PROTO_HEADER_VERSION 30
|
||||
#define PB_PROTO_HEADER_VERSION 40
|
||||
|
||||
/* These macros are used to declare pb_field_t's in the constant array. */
|
||||
/* Size of a structure member, in bytes. */
|
||||
|
@ -394,103 +498,356 @@ struct pb_extension_s {
|
|||
#define pb_arraysize(st, m) (pb_membersize(st, m) / pb_membersize(st, m[0]))
|
||||
/* Delta from start of one member to the start of another member. */
|
||||
#define pb_delta(st, m1, m2) ((int)offsetof(st, m1) - (int)offsetof(st, m2))
|
||||
/* Marks the end of the field list */
|
||||
#define PB_LAST_FIELD {0,(pb_type_t) 0,0,0,0,0,0}
|
||||
|
||||
/* Macros for filling in the data_offset field */
|
||||
/* data_offset for first field in a message */
|
||||
#define PB_DATAOFFSET_FIRST(st, m1, m2) (offsetof(st, m1))
|
||||
/* data_offset for subsequent fields */
|
||||
#define PB_DATAOFFSET_OTHER(st, m1, m2) (offsetof(st, m1) - offsetof(st, m2) - pb_membersize(st, m2))
|
||||
/* data offset for subsequent fields inside an union (oneof) */
|
||||
#define PB_DATAOFFSET_UNION(st, m1, m2) (PB_SIZE_MAX)
|
||||
/* Choose first/other based on m1 == m2 (deprecated, remains for backwards compatibility) */
|
||||
#define PB_DATAOFFSET_CHOOSE(st, m1, m2) (int)(offsetof(st, m1) == offsetof(st, m2) \
|
||||
? PB_DATAOFFSET_FIRST(st, m1, m2) \
|
||||
: PB_DATAOFFSET_OTHER(st, m1, m2))
|
||||
/* Force expansion of macro value */
|
||||
#define PB_EXPAND(x) x
|
||||
|
||||
/* Required fields are the simplest. They just have delta (padding) from
|
||||
* previous field end, and the size of the field. Pointer is used for
|
||||
* submessages and default values.
|
||||
/* Binding of a message field set into a specific structure */
|
||||
#define PB_BIND(msgname, structname, width) \
|
||||
const uint32_t structname ## _field_info[] PB_PROGMEM = \
|
||||
{ \
|
||||
msgname ## _FIELDLIST(PB_GEN_FIELD_INFO_ ## width, structname) \
|
||||
0 \
|
||||
}; \
|
||||
const pb_msgdesc_t* const structname ## _submsg_info[] = \
|
||||
{ \
|
||||
msgname ## _FIELDLIST(PB_GEN_SUBMSG_INFO, structname) \
|
||||
NULL \
|
||||
}; \
|
||||
const pb_msgdesc_t structname ## _msg = \
|
||||
{ \
|
||||
structname ## _field_info, \
|
||||
structname ## _submsg_info, \
|
||||
msgname ## _DEFAULT, \
|
||||
msgname ## _CALLBACK, \
|
||||
0 msgname ## _FIELDLIST(PB_GEN_FIELD_COUNT, structname), \
|
||||
0 msgname ## _FIELDLIST(PB_GEN_REQ_FIELD_COUNT, structname), \
|
||||
0 msgname ## _FIELDLIST(PB_GEN_LARGEST_TAG, structname), \
|
||||
}; \
|
||||
msgname ## _FIELDLIST(PB_GEN_FIELD_INFO_ASSERT_ ## width, structname)
|
||||
|
||||
#define PB_GEN_FIELD_COUNT(structname, atype, htype, ltype, fieldname, tag) +1
|
||||
#define PB_GEN_REQ_FIELD_COUNT(structname, atype, htype, ltype, fieldname, tag) \
|
||||
+ (PB_HTYPE_ ## htype == PB_HTYPE_REQUIRED)
|
||||
#define PB_GEN_LARGEST_TAG(structname, atype, htype, ltype, fieldname, tag) \
|
||||
* 0 + tag
|
||||
|
||||
/* X-macro for generating the entries in struct_field_info[] array. */
|
||||
#define PB_GEN_FIELD_INFO_1(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_1(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_2(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_2(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_4(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_4(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_8(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_8(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_AUTO(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_AUTO2(PB_FIELDINFO_WIDTH_AUTO(_PB_ATYPE_ ## atype, _PB_HTYPE_ ## htype, _PB_LTYPE_ ## ltype), \
|
||||
tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_FIELDINFO_AUTO2(width, tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_FIELDINFO_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size)
|
||||
|
||||
#define PB_FIELDINFO_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_FIELDINFO_ ## width(tag, type, data_offset, data_size, size_offset, array_size)
|
||||
|
||||
/* X-macro for generating asserts that entries fit in struct_field_info[] array.
|
||||
* The structure of macros here must match the structure above in PB_GEN_FIELD_INFO_x(),
|
||||
* but it is not easily reused because of how macro substitutions work. */
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_1(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_ASSERT_1(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_2(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_ASSERT_2(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_4(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_ASSERT_4(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_8(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_ASSERT_8(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_AUTO(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_ASSERT_AUTO2(PB_FIELDINFO_WIDTH_AUTO(_PB_ATYPE_ ## atype, _PB_HTYPE_ ## htype, _PB_LTYPE_ ## ltype), \
|
||||
tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_FIELDINFO_ASSERT_AUTO2(width, tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_FIELDINFO_ASSERT_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size)
|
||||
|
||||
#define PB_FIELDINFO_ASSERT_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_FIELDINFO_ASSERT_ ## width(tag, type, data_offset, data_size, size_offset, array_size)
|
||||
|
||||
#define PB_DATA_OFFSET_STATIC(htype, structname, fieldname) PB_DO ## htype(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_POINTER(htype, structname, fieldname) PB_DO ## htype(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_CALLBACK(htype, structname, fieldname) PB_DO ## htype(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_REQUIRED(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_SINGULAR(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_ONEOF(structname, fieldname) offsetof(structname, PB_ONEOF_NAME(FULL, fieldname))
|
||||
#define PB_DO_PB_HTYPE_OPTIONAL(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_REPEATED(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_FIXARRAY(structname, fieldname) offsetof(structname, fieldname)
|
||||
|
||||
#define PB_SIZE_OFFSET_STATIC(htype, structname, fieldname) PB_SO ## htype(structname, fieldname)
|
||||
#define PB_SIZE_OFFSET_POINTER(htype, structname, fieldname) PB_SO_PTR ## htype(structname, fieldname)
|
||||
#define PB_SIZE_OFFSET_CALLBACK(htype, structname, fieldname) PB_SO_CB ## htype(structname, fieldname)
|
||||
#define PB_SO_PB_HTYPE_REQUIRED(structname, fieldname) 0
|
||||
#define PB_SO_PB_HTYPE_SINGULAR(structname, fieldname) 0
|
||||
#define PB_SO_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF2(structname, PB_ONEOF_NAME(FULL, fieldname), PB_ONEOF_NAME(UNION, fieldname))
|
||||
#define PB_SO_PB_HTYPE_ONEOF2(structname, fullname, unionname) PB_SO_PB_HTYPE_ONEOF3(structname, fullname, unionname)
|
||||
#define PB_SO_PB_HTYPE_ONEOF3(structname, fullname, unionname) pb_delta(structname, fullname, which_ ## unionname)
|
||||
#define PB_SO_PB_HTYPE_OPTIONAL(structname, fieldname) pb_delta(structname, fieldname, has_ ## fieldname)
|
||||
#define PB_SO_PB_HTYPE_REPEATED(structname, fieldname) pb_delta(structname, fieldname, fieldname ## _count)
|
||||
#define PB_SO_PB_HTYPE_FIXARRAY(structname, fieldname) 0
|
||||
#define PB_SO_PTR_PB_HTYPE_REQUIRED(structname, fieldname) 0
|
||||
#define PB_SO_PTR_PB_HTYPE_SINGULAR(structname, fieldname) 0
|
||||
#define PB_SO_PTR_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF(structname, fieldname)
|
||||
#define PB_SO_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) 0
|
||||
#define PB_SO_PTR_PB_HTYPE_REPEATED(structname, fieldname) PB_SO_PB_HTYPE_REPEATED(structname, fieldname)
|
||||
#define PB_SO_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_REQUIRED(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_SINGULAR(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF(structname, fieldname)
|
||||
#define PB_SO_CB_PB_HTYPE_OPTIONAL(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_REPEATED(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_FIXARRAY(structname, fieldname) 0
|
||||
|
||||
#define PB_ARRAY_SIZE_STATIC(htype, structname, fieldname) PB_AS ## htype(structname, fieldname)
|
||||
#define PB_ARRAY_SIZE_POINTER(htype, structname, fieldname) PB_AS_PTR ## htype(structname, fieldname)
|
||||
#define PB_ARRAY_SIZE_CALLBACK(htype, structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_REQUIRED(structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_SINGULAR(structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_OPTIONAL(structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_ONEOF(structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_REPEATED(structname, fieldname) pb_arraysize(structname, fieldname)
|
||||
#define PB_AS_PB_HTYPE_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname)
|
||||
#define PB_AS_PTR_PB_HTYPE_REQUIRED(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_SINGULAR(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_ONEOF(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_REPEATED(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname[0])
|
||||
|
||||
#define PB_DATA_SIZE_STATIC(htype, structname, fieldname) PB_DS ## htype(structname, fieldname)
|
||||
#define PB_DATA_SIZE_POINTER(htype, structname, fieldname) PB_DS_PTR ## htype(structname, fieldname)
|
||||
#define PB_DATA_SIZE_CALLBACK(htype, structname, fieldname) PB_DS_CB ## htype(structname, fieldname)
|
||||
#define PB_DS_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname))
|
||||
#define PB_DS_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0][0])
|
||||
#define PB_DS_CB_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_CB_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_CB_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_CB_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname))
|
||||
#define PB_DS_CB_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_CB_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
|
||||
#define PB_ONEOF_NAME(type, tuple) PB_EXPAND(PB_ONEOF_NAME_ ## type tuple)
|
||||
#define PB_ONEOF_NAME_UNION(unionname,membername,fullname) unionname
|
||||
#define PB_ONEOF_NAME_MEMBER(unionname,membername,fullname) membername
|
||||
#define PB_ONEOF_NAME_FULL(unionname,membername,fullname) fullname
|
||||
|
||||
#define PB_GEN_SUBMSG_INFO(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_SUBMSG_INFO_ ## htype(_PB_LTYPE_ ## ltype, structname, fieldname)
|
||||
|
||||
#define PB_SUBMSG_INFO_REQUIRED(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_SINGULAR(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_OPTIONAL(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_ONEOF(ltype, structname, fieldname) PB_SUBMSG_INFO_ONEOF2(ltype, structname, PB_ONEOF_NAME(UNION, fieldname), PB_ONEOF_NAME(MEMBER, fieldname))
|
||||
#define PB_SUBMSG_INFO_ONEOF2(ltype, structname, unionname, membername) PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername)
|
||||
#define PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername) PB_SI ## ltype(structname ## _ ## unionname ## _ ## membername ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_REPEATED(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_FIXARRAY(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SI_PB_LTYPE_BOOL(t)
|
||||
#define PB_SI_PB_LTYPE_BYTES(t)
|
||||
#define PB_SI_PB_LTYPE_DOUBLE(t)
|
||||
#define PB_SI_PB_LTYPE_ENUM(t)
|
||||
#define PB_SI_PB_LTYPE_UENUM(t)
|
||||
#define PB_SI_PB_LTYPE_FIXED32(t)
|
||||
#define PB_SI_PB_LTYPE_FIXED64(t)
|
||||
#define PB_SI_PB_LTYPE_FLOAT(t)
|
||||
#define PB_SI_PB_LTYPE_INT32(t)
|
||||
#define PB_SI_PB_LTYPE_INT64(t)
|
||||
#define PB_SI_PB_LTYPE_MESSAGE(t) PB_SUBMSG_DESCRIPTOR(t)
|
||||
#define PB_SI_PB_LTYPE_MSG_W_CB(t) PB_SUBMSG_DESCRIPTOR(t)
|
||||
#define PB_SI_PB_LTYPE_SFIXED32(t)
|
||||
#define PB_SI_PB_LTYPE_SFIXED64(t)
|
||||
#define PB_SI_PB_LTYPE_SINT32(t)
|
||||
#define PB_SI_PB_LTYPE_SINT64(t)
|
||||
#define PB_SI_PB_LTYPE_STRING(t)
|
||||
#define PB_SI_PB_LTYPE_UINT32(t)
|
||||
#define PB_SI_PB_LTYPE_UINT64(t)
|
||||
#define PB_SI_PB_LTYPE_EXTENSION(t)
|
||||
#define PB_SI_PB_LTYPE_FIXED_LENGTH_BYTES(t)
|
||||
#define PB_SUBMSG_DESCRIPTOR(t) &(t ## _msg),
|
||||
|
||||
/* The field descriptors use a variable width format, with width of either
|
||||
* 1, 2, 4 or 8 of 32-bit words. The two lowest bytes of the first byte always
|
||||
* encode the descriptor size, 6 lowest bits of field tag number, and 8 bits
|
||||
* of the field type.
|
||||
*
|
||||
* Descriptor size is encoded as 0 = 1 word, 1 = 2 words, 2 = 4 words, 3 = 8 words.
|
||||
*
|
||||
* Formats, listed starting with the least significant bit of the first word.
|
||||
* 1 word: [2-bit len] [6-bit tag] [8-bit type] [8-bit data_offset] [4-bit size_offset] [4-bit data_size]
|
||||
*
|
||||
* 2 words: [2-bit len] [6-bit tag] [8-bit type] [12-bit array_size] [4-bit size_offset]
|
||||
* [16-bit data_offset] [12-bit data_size] [4-bit tag>>6]
|
||||
*
|
||||
* 4 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit array_size]
|
||||
* [8-bit size_offset] [24-bit tag>>6]
|
||||
* [32-bit data_offset]
|
||||
* [32-bit data_size]
|
||||
*
|
||||
* 8 words: [2-bit len] [6-bit tag] [8-bit type] [16-bit reserved]
|
||||
* [8-bit size_offset] [24-bit tag>>6]
|
||||
* [32-bit data_offset]
|
||||
* [32-bit data_size]
|
||||
* [32-bit array_size]
|
||||
* [32-bit reserved]
|
||||
* [32-bit reserved]
|
||||
* [32-bit reserved]
|
||||
*/
|
||||
#define PB_REQUIRED_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
/* Optional fields add the delta to the has_ variable. */
|
||||
#define PB_OPTIONAL_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, \
|
||||
pb_delta(st, has_ ## m, m), \
|
||||
pb_membersize(st, m), 0, ptr}
|
||||
#define PB_FIELDINFO_1(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
(0 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(data_offset) & 0xFF) << 16) | \
|
||||
(((uint32_t)(size_offset) & 0x0F) << 24) | (((uint32_t)(data_size) & 0x0F) << 28)),
|
||||
|
||||
#define PB_SINGULAR_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
#define PB_FIELDINFO_2(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
(1 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(array_size) & 0xFFF) << 16) | (((uint32_t)(size_offset) & 0x0F) << 28)), \
|
||||
(((uint32_t)(data_offset) & 0xFFFF) | (((uint32_t)(data_size) & 0xFFF) << 16) | (((uint32_t)(tag) & 0x3c0) << 22)),
|
||||
|
||||
/* Repeated fields have a _count field and also the maximum number of entries. */
|
||||
#define PB_REPEATED_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | ltype, \
|
||||
fd, \
|
||||
pb_delta(st, m ## _count, m), \
|
||||
pb_membersize(st, m[0]), \
|
||||
pb_arraysize(st, m), ptr}
|
||||
#define PB_FIELDINFO_4(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
(2 | (((tag) << 2) & 0xFF) | ((type) << 8) | (((uint32_t)(array_size) & 0xFFFF) << 16)), \
|
||||
((uint32_t)(int_least8_t)(size_offset) | (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \
|
||||
(data_offset), (data_size),
|
||||
|
||||
/* Allocated fields carry the size of the actual data, not the pointer */
|
||||
#define PB_REQUIRED_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_REQUIRED | ltype, \
|
||||
fd, 0, pb_membersize(st, m[0]), 0, ptr}
|
||||
#define PB_FIELDINFO_8(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
(3 | (((tag) << 2) & 0xFF) | ((type) << 8)), \
|
||||
((uint32_t)(int_least8_t)(size_offset) | (((uint32_t)(tag) << 2) & 0xFFFFFF00)), \
|
||||
(data_offset), (data_size), (array_size), 0, 0, 0,
|
||||
|
||||
/* Optional fields don't need a has_ variable, as information would be redundant */
|
||||
#define PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, 0, pb_membersize(st, m[0]), 0, ptr}
|
||||
|
||||
/* Same as optional fields*/
|
||||
#define PB_SINGULAR_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, 0, pb_membersize(st, m[0]), 0, ptr}
|
||||
|
||||
/* Repeated fields have a _count field and a pointer to array of pointers */
|
||||
#define PB_REPEATED_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_REPEATED | ltype, \
|
||||
fd, pb_delta(st, m ## _count, m), \
|
||||
pb_membersize(st, m[0]), 0, ptr}
|
||||
|
||||
/* Callbacks are much like required fields except with special datatype. */
|
||||
#define PB_REQUIRED_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_CALLBACK | PB_HTYPE_REQUIRED | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_SINGULAR_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_CALLBACK | PB_HTYPE_OPTIONAL | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_REPEATED_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_CALLBACK | PB_HTYPE_REPEATED | ltype, \
|
||||
fd, 0, pb_membersize(st, m), 0, ptr}
|
||||
|
||||
/* Optional extensions don't have the has_ field, as that would be redundant.
|
||||
* Furthermore, the combination of OPTIONAL without has_ field is used
|
||||
* for indicating proto3 style fields. Extensions exist in proto2 mode only,
|
||||
* so they should be encoded according to proto2 rules. To avoid the conflict,
|
||||
* extensions are marked as REQUIRED instead.
|
||||
/* These assertions verify that the field information fits in the allocated space.
|
||||
* The generator tries to automatically determine the correct width that can fit all
|
||||
* data associated with a message. These asserts will fail only if there has been a
|
||||
* problem in the automatic logic - this may be worth reporting as a bug. As a workaround,
|
||||
* you can increase the descriptor width by defining PB_FIELDINFO_WIDTH or by setting
|
||||
* descriptorsize option in .options file.
|
||||
*/
|
||||
#define PB_OPTEXT_STATIC(tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_REQUIRED | ltype, \
|
||||
0, \
|
||||
0, \
|
||||
pb_membersize(st, m), 0, ptr}
|
||||
#define PB_FITS(value,bits) ((uint32_t)(value) < ((uint32_t)1<<bits))
|
||||
#define PB_FIELDINFO_ASSERT_1(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_STATIC_ASSERT(PB_FITS(tag,6) && PB_FITS(data_offset,8) && PB_FITS(size_offset,4) && PB_FITS(data_size,4) && PB_FITS(array_size,1), FIELDINFO_DOES_NOT_FIT_width1_field ## tag)
|
||||
|
||||
#define PB_OPTEXT_POINTER(tag, st, m, fd, ltype, ptr) \
|
||||
PB_OPTIONAL_POINTER(tag, st, m, fd, ltype, ptr)
|
||||
#define PB_FIELDINFO_ASSERT_2(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_STATIC_ASSERT(PB_FITS(tag,10) && PB_FITS(data_offset,16) && PB_FITS(size_offset,4) && PB_FITS(data_size,12) && PB_FITS(array_size,12), FIELDINFO_DOES_NOT_FIT_width2_field ## tag)
|
||||
|
||||
#define PB_OPTEXT_CALLBACK(tag, st, m, fd, ltype, ptr) \
|
||||
PB_OPTIONAL_CALLBACK(tag, st, m, fd, ltype, ptr)
|
||||
#ifndef PB_FIELD_32BIT
|
||||
/* Maximum field sizes are still 16-bit if pb_size_t is 16-bit */
|
||||
#define PB_FIELDINFO_ASSERT_4(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_STATIC_ASSERT(PB_FITS(tag,16) && PB_FITS(data_offset,16) && PB_FITS((int_least8_t)size_offset,8) && PB_FITS(data_size,16) && PB_FITS(array_size,16), FIELDINFO_DOES_NOT_FIT_width4_field ## tag)
|
||||
|
||||
#define PB_FIELDINFO_ASSERT_8(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_STATIC_ASSERT(PB_FITS(tag,16) && PB_FITS(data_offset,16) && PB_FITS((int_least8_t)size_offset,8) && PB_FITS(data_size,16) && PB_FITS(array_size,16), FIELDINFO_DOES_NOT_FIT_width8_field ## tag)
|
||||
#else
|
||||
/* Up to 32-bit fields supported.
|
||||
* Note that the checks are against 31 bits to avoid compiler warnings about shift wider than type in the test.
|
||||
* I expect that there is no reasonable use for >2GB messages with nanopb anyway.
|
||||
*/
|
||||
#define PB_FIELDINFO_ASSERT_4(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_STATIC_ASSERT(PB_FITS(tag,30) && PB_FITS(data_offset,31) && PB_FITS(size_offset,8) && PB_FITS(data_size,31) && PB_FITS(array_size,16), FIELDINFO_DOES_NOT_FIT_width4_field ## tag)
|
||||
|
||||
#define PB_FIELDINFO_ASSERT_8(tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_STATIC_ASSERT(PB_FITS(tag,30) && PB_FITS(data_offset,31) && PB_FITS(size_offset,8) && PB_FITS(data_size,31) && PB_FITS(array_size,31), FIELDINFO_DOES_NOT_FIT_width8_field ## tag)
|
||||
#endif
|
||||
|
||||
|
||||
/* Automatic picking of FIELDINFO width:
|
||||
* Uses width 1 when possible, otherwise resorts to width 2.
|
||||
* This is used when PB_BIND() is called with "AUTO" as the argument.
|
||||
* The generator will give explicit size argument when it knows that a message
|
||||
* structure grows beyond 1-word format limits.
|
||||
*/
|
||||
#define PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype) PB_FI_WIDTH ## atype(htype, ltype)
|
||||
#define PB_FI_WIDTH_PB_ATYPE_STATIC(htype, ltype) PB_FI_WIDTH ## htype(ltype)
|
||||
#define PB_FI_WIDTH_PB_ATYPE_POINTER(htype, ltype) PB_FI_WIDTH ## htype(ltype)
|
||||
#define PB_FI_WIDTH_PB_ATYPE_CALLBACK(htype, ltype) 2
|
||||
#define PB_FI_WIDTH_PB_HTYPE_REQUIRED(ltype) PB_FI_WIDTH ## ltype
|
||||
#define PB_FI_WIDTH_PB_HTYPE_SINGULAR(ltype) PB_FI_WIDTH ## ltype
|
||||
#define PB_FI_WIDTH_PB_HTYPE_OPTIONAL(ltype) PB_FI_WIDTH ## ltype
|
||||
#define PB_FI_WIDTH_PB_HTYPE_ONEOF(ltype) PB_FI_WIDTH ## ltype
|
||||
#define PB_FI_WIDTH_PB_HTYPE_REPEATED(ltype) 2
|
||||
#define PB_FI_WIDTH_PB_HTYPE_FIXARRAY(ltype) 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_BOOL 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_BYTES 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_DOUBLE 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_ENUM 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_UENUM 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_FIXED32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_FIXED64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_FLOAT 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_INT32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_INT64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_MESSAGE 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_MSG_W_CB 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_SFIXED32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_SFIXED64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_SINT32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_SINT64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_STRING 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_UINT32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_UINT64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_EXTENSION 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_FIXED_LENGTH_BYTES 2
|
||||
|
||||
/* The mapping from protobuf types to LTYPEs is done using these macros. */
|
||||
#define PB_LTYPE_MAP_BOOL PB_LTYPE_BOOL
|
||||
|
@ -504,6 +861,7 @@ struct pb_extension_s {
|
|||
#define PB_LTYPE_MAP_INT32 PB_LTYPE_VARINT
|
||||
#define PB_LTYPE_MAP_INT64 PB_LTYPE_VARINT
|
||||
#define PB_LTYPE_MAP_MESSAGE PB_LTYPE_SUBMESSAGE
|
||||
#define PB_LTYPE_MAP_MSG_W_CB PB_LTYPE_SUBMSG_W_CB
|
||||
#define PB_LTYPE_MAP_SFIXED32 PB_LTYPE_FIXED32
|
||||
#define PB_LTYPE_MAP_SFIXED64 PB_LTYPE_FIXED64
|
||||
#define PB_LTYPE_MAP_SINT32 PB_LTYPE_SVARINT
|
||||
|
@ -514,67 +872,6 @@ struct pb_extension_s {
|
|||
#define PB_LTYPE_MAP_EXTENSION PB_LTYPE_EXTENSION
|
||||
#define PB_LTYPE_MAP_FIXED_LENGTH_BYTES PB_LTYPE_FIXED_LENGTH_BYTES
|
||||
|
||||
/* This is the actual macro used in field descriptions.
|
||||
* It takes these arguments:
|
||||
* - Field tag number
|
||||
* - Field type: BOOL, BYTES, DOUBLE, ENUM, UENUM, FIXED32, FIXED64,
|
||||
* FLOAT, INT32, INT64, MESSAGE, SFIXED32, SFIXED64
|
||||
* SINT32, SINT64, STRING, UINT32, UINT64 or EXTENSION
|
||||
* - Field rules: REQUIRED, OPTIONAL or REPEATED
|
||||
* - Allocation: STATIC, CALLBACK or POINTER
|
||||
* - Placement: FIRST or OTHER, depending on if this is the first field in structure.
|
||||
* - Message name
|
||||
* - Field name
|
||||
* - Previous field name (or field name again for first field)
|
||||
* - Pointer to default value or submsg fields.
|
||||
*/
|
||||
|
||||
#define PB_FIELD(tag, type, rules, allocation, placement, message, field, prevfield, ptr) \
|
||||
PB_ ## rules ## _ ## allocation(tag, message, field, \
|
||||
PB_DATAOFFSET_ ## placement(message, field, prevfield), \
|
||||
PB_LTYPE_MAP_ ## type, ptr)
|
||||
|
||||
/* Field description for repeated static fixed count fields.*/
|
||||
#define PB_REPEATED_FIXED_COUNT(tag, type, placement, message, field, prevfield, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_REPEATED | PB_LTYPE_MAP_ ## type, \
|
||||
PB_DATAOFFSET_ ## placement(message, field, prevfield), \
|
||||
0, \
|
||||
pb_membersize(message, field[0]), \
|
||||
pb_arraysize(message, field), ptr}
|
||||
|
||||
/* Field description for oneof fields. This requires taking into account the
|
||||
* union name also, that's why a separate set of macros is needed.
|
||||
*/
|
||||
#define PB_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \
|
||||
fd, pb_delta(st, which_ ## u, u.m), \
|
||||
pb_membersize(st, u.m), 0, ptr}
|
||||
|
||||
#define PB_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \
|
||||
fd, pb_delta(st, which_ ## u, u.m), \
|
||||
pb_membersize(st, u.m[0]), 0, ptr}
|
||||
|
||||
#define PB_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \
|
||||
PB_ONEOF_ ## allocation(union_name, tag, message, field, \
|
||||
PB_DATAOFFSET_ ## placement(message, union_name.field, prevfield), \
|
||||
PB_LTYPE_MAP_ ## type, ptr)
|
||||
|
||||
#define PB_ANONYMOUS_ONEOF_STATIC(u, tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_STATIC | PB_HTYPE_ONEOF | ltype, \
|
||||
fd, pb_delta(st, which_ ## u, m), \
|
||||
pb_membersize(st, m), 0, ptr}
|
||||
|
||||
#define PB_ANONYMOUS_ONEOF_POINTER(u, tag, st, m, fd, ltype, ptr) \
|
||||
{tag, PB_ATYPE_POINTER | PB_HTYPE_ONEOF | ltype, \
|
||||
fd, pb_delta(st, which_ ## u, m), \
|
||||
pb_membersize(st, m[0]), 0, ptr}
|
||||
|
||||
#define PB_ANONYMOUS_ONEOF_FIELD(union_name, tag, type, rules, allocation, placement, message, field, prevfield, ptr) \
|
||||
PB_ANONYMOUS_ONEOF_ ## allocation(union_name, tag, message, field, \
|
||||
PB_DATAOFFSET_ ## placement(message, field, prevfield), \
|
||||
PB_LTYPE_MAP_ ## type, ptr)
|
||||
|
||||
/* These macros are used for giving out error messages.
|
||||
* They are mostly a debugging aid; the main error information
|
||||
* is the true/false return value from functions.
|
||||
|
@ -597,4 +894,30 @@ struct pb_extension_s {
|
|||
|
||||
#define PB_RETURN_ERROR(stream, msg) return PB_SET_ERROR(stream, msg), false
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus >= 201103L
|
||||
#define PB_CONSTEXPR constexpr
|
||||
#else // __cplusplus >= 201103L
|
||||
#define PB_CONSTEXPR
|
||||
#endif // __cplusplus >= 201103L
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#define PB_INLINE_CONSTEXPR inline constexpr
|
||||
#else // __cplusplus >= 201703L
|
||||
#define PB_INLINE_CONSTEXPR PB_CONSTEXPR
|
||||
#endif // __cplusplus >= 201703L
|
||||
|
||||
extern "C++"
|
||||
{
|
||||
namespace nanopb {
|
||||
// Each type will be partially specialized by the generator.
|
||||
template <typename GenMessageT> struct MessageDescriptor;
|
||||
} // namespace nanopb
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -5,102 +5,384 @@
|
|||
|
||||
#include "pb_common.h"
|
||||
|
||||
bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct)
|
||||
static bool load_descriptor_values(pb_field_iter_t *iter)
|
||||
{
|
||||
iter->start = fields;
|
||||
iter->pos = fields;
|
||||
iter->required_field_index = 0;
|
||||
iter->dest_struct = dest_struct;
|
||||
uint32_t word0;
|
||||
uint32_t data_offset;
|
||||
int_least8_t size_offset;
|
||||
|
||||
if (!dest_struct)
|
||||
if (iter->index >= iter->descriptor->field_count)
|
||||
return false;
|
||||
|
||||
word0 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
|
||||
iter->type = (pb_type_t)((word0 >> 8) & 0xFF);
|
||||
|
||||
switch(word0 & 3)
|
||||
{
|
||||
iter->pData = NULL;
|
||||
case 0: {
|
||||
/* 1-word format */
|
||||
iter->array_size = 1;
|
||||
iter->tag = (pb_size_t)((word0 >> 2) & 0x3F);
|
||||
size_offset = (int_least8_t)((word0 >> 24) & 0x0F);
|
||||
data_offset = (word0 >> 16) & 0xFF;
|
||||
iter->data_size = (pb_size_t)((word0 >> 28) & 0x0F);
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
/* 2-word format */
|
||||
uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
|
||||
|
||||
iter->array_size = (pb_size_t)((word0 >> 16) & 0x0FFF);
|
||||
iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 28) << 6));
|
||||
size_offset = (int_least8_t)((word0 >> 28) & 0x0F);
|
||||
data_offset = word1 & 0xFFFF;
|
||||
iter->data_size = (pb_size_t)((word1 >> 16) & 0x0FFF);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
/* 4-word format */
|
||||
uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
|
||||
uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]);
|
||||
uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]);
|
||||
|
||||
iter->array_size = (pb_size_t)(word0 >> 16);
|
||||
iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6));
|
||||
size_offset = (int_least8_t)(word1 & 0xFF);
|
||||
data_offset = word2;
|
||||
iter->data_size = (pb_size_t)word3;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
/* 8-word format */
|
||||
uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
|
||||
uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]);
|
||||
uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]);
|
||||
uint32_t word4 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 4]);
|
||||
|
||||
iter->array_size = (pb_size_t)word4;
|
||||
iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6));
|
||||
size_offset = (int_least8_t)(word1 & 0xFF);
|
||||
data_offset = word2;
|
||||
iter->data_size = (pb_size_t)word3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!iter->message)
|
||||
{
|
||||
/* Avoid doing arithmetic on null pointers, it is undefined */
|
||||
iter->pField = NULL;
|
||||
iter->pSize = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->pData = (char*)dest_struct + iter->pos->data_offset;
|
||||
iter->pSize = (char*)iter->pData + iter->pos->size_offset;
|
||||
iter->pField = (char*)iter->message + data_offset;
|
||||
|
||||
if (size_offset)
|
||||
{
|
||||
iter->pSize = (char*)iter->pField - size_offset;
|
||||
}
|
||||
else if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED &&
|
||||
(PB_ATYPE(iter->type) == PB_ATYPE_STATIC ||
|
||||
PB_ATYPE(iter->type) == PB_ATYPE_POINTER))
|
||||
{
|
||||
/* Fixed count array */
|
||||
iter->pSize = &iter->array_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->pSize = NULL;
|
||||
}
|
||||
|
||||
return (iter->pos->tag != 0);
|
||||
if (PB_ATYPE(iter->type) == PB_ATYPE_POINTER && iter->pField != NULL)
|
||||
{
|
||||
iter->pData = *(void**)iter->pField;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->pData = iter->pField;
|
||||
}
|
||||
}
|
||||
|
||||
if (PB_LTYPE_IS_SUBMSG(iter->type))
|
||||
{
|
||||
iter->submsg_desc = iter->descriptor->submsg_info[iter->submessage_index];
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->submsg_desc = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void advance_iterator(pb_field_iter_t *iter)
|
||||
{
|
||||
iter->index++;
|
||||
|
||||
if (iter->index >= iter->descriptor->field_count)
|
||||
{
|
||||
/* Restart */
|
||||
iter->index = 0;
|
||||
iter->field_info_index = 0;
|
||||
iter->submessage_index = 0;
|
||||
iter->required_field_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Increment indexes based on previous field type.
|
||||
* All field info formats have the following fields:
|
||||
* - lowest 2 bits tell the amount of words in the descriptor (2^n words)
|
||||
* - bits 2..7 give the lowest bits of tag number.
|
||||
* - bits 8..15 give the field type.
|
||||
*/
|
||||
uint32_t prev_descriptor = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
|
||||
pb_type_t prev_type = (prev_descriptor >> 8) & 0xFF;
|
||||
pb_size_t descriptor_len = (pb_size_t)(1 << (prev_descriptor & 3));
|
||||
|
||||
/* Add to fields.
|
||||
* The cast to pb_size_t is needed to avoid -Wconversion warning.
|
||||
* Because the data is is constants from generator, there is no danger of overflow.
|
||||
*/
|
||||
iter->field_info_index = (pb_size_t)(iter->field_info_index + descriptor_len);
|
||||
iter->required_field_index = (pb_size_t)(iter->required_field_index + (PB_HTYPE(prev_type) == PB_HTYPE_REQUIRED));
|
||||
iter->submessage_index = (pb_size_t)(iter->submessage_index + PB_LTYPE_IS_SUBMSG(prev_type));
|
||||
}
|
||||
}
|
||||
|
||||
bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message)
|
||||
{
|
||||
memset(iter, 0, sizeof(*iter));
|
||||
|
||||
iter->descriptor = desc;
|
||||
iter->message = message;
|
||||
|
||||
return load_descriptor_values(iter);
|
||||
}
|
||||
|
||||
bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension)
|
||||
{
|
||||
const pb_msgdesc_t *msg = (const pb_msgdesc_t*)extension->type->arg;
|
||||
bool status;
|
||||
|
||||
uint32_t word0 = PB_PROGMEM_READU32(msg->field_info[0]);
|
||||
if (PB_ATYPE(word0 >> 8) == PB_ATYPE_POINTER)
|
||||
{
|
||||
/* For pointer extensions, the pointer is stored directly
|
||||
* in the extension structure. This avoids having an extra
|
||||
* indirection. */
|
||||
status = pb_field_iter_begin(iter, msg, &extension->dest);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = pb_field_iter_begin(iter, msg, extension->dest);
|
||||
}
|
||||
|
||||
iter->pSize = &extension->found;
|
||||
return status;
|
||||
}
|
||||
|
||||
bool pb_field_iter_next(pb_field_iter_t *iter)
|
||||
{
|
||||
const pb_field_t *prev_field = iter->pos;
|
||||
|
||||
if (prev_field->tag == 0)
|
||||
{
|
||||
/* Handle empty message types, where the first field is already the terminator.
|
||||
* In other cases, the iter->pos never points to the terminator. */
|
||||
return false;
|
||||
}
|
||||
|
||||
iter->pos++;
|
||||
|
||||
if (iter->pos->tag == 0)
|
||||
{
|
||||
/* Wrapped back to beginning, reinitialize */
|
||||
(void)pb_field_iter_begin(iter, iter->start, iter->dest_struct);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Increment the pointers based on previous field size */
|
||||
size_t prev_size = prev_field->data_size;
|
||||
|
||||
if (PB_HTYPE(prev_field->type) == PB_HTYPE_ONEOF &&
|
||||
PB_HTYPE(iter->pos->type) == PB_HTYPE_ONEOF &&
|
||||
iter->pos->data_offset == PB_SIZE_MAX)
|
||||
{
|
||||
/* Don't advance pointers inside unions */
|
||||
return true;
|
||||
}
|
||||
else if (PB_ATYPE(prev_field->type) == PB_ATYPE_STATIC &&
|
||||
PB_HTYPE(prev_field->type) == PB_HTYPE_REPEATED)
|
||||
{
|
||||
/* In static arrays, the data_size tells the size of a single entry and
|
||||
* array_size is the number of entries */
|
||||
prev_size *= prev_field->array_size;
|
||||
}
|
||||
else if (PB_ATYPE(prev_field->type) == PB_ATYPE_POINTER)
|
||||
{
|
||||
/* Pointer fields always have a constant size in the main structure.
|
||||
* The data_size only applies to the dynamically allocated area. */
|
||||
prev_size = sizeof(void*);
|
||||
}
|
||||
|
||||
if (PB_HTYPE(prev_field->type) == PB_HTYPE_REQUIRED)
|
||||
{
|
||||
/* Count the required fields, in order to check their presence in the
|
||||
* decoder. */
|
||||
iter->required_field_index++;
|
||||
}
|
||||
|
||||
iter->pData = (char*)iter->pData + prev_size + iter->pos->data_offset;
|
||||
iter->pSize = (char*)iter->pData + iter->pos->size_offset;
|
||||
return true;
|
||||
}
|
||||
advance_iterator(iter);
|
||||
(void)load_descriptor_values(iter);
|
||||
return iter->index != 0;
|
||||
}
|
||||
|
||||
bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag)
|
||||
{
|
||||
const pb_field_t *start = iter->pos;
|
||||
|
||||
do {
|
||||
if (iter->pos->tag == tag &&
|
||||
PB_LTYPE(iter->pos->type) != PB_LTYPE_EXTENSION)
|
||||
if (iter->tag == tag)
|
||||
{
|
||||
/* Found the wanted field */
|
||||
return true; /* Nothing to do, correct field already. */
|
||||
}
|
||||
else if (tag > iter->descriptor->largest_tag)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pb_size_t start = iter->index;
|
||||
uint32_t fieldinfo;
|
||||
|
||||
if (tag < iter->tag)
|
||||
{
|
||||
/* Fields are in tag number order, so we know that tag is between
|
||||
* 0 and our start position. Setting index to end forces
|
||||
* advance_iterator() call below to restart from beginning. */
|
||||
iter->index = iter->descriptor->field_count;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* Advance iterator but don't load values yet */
|
||||
advance_iterator(iter);
|
||||
|
||||
/* Do fast check for tag number match */
|
||||
fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
|
||||
|
||||
if (((fieldinfo >> 2) & 0x3F) == (tag & 0x3F))
|
||||
{
|
||||
/* Good candidate, check further */
|
||||
(void)load_descriptor_values(iter);
|
||||
|
||||
if (iter->tag == tag &&
|
||||
PB_LTYPE(iter->type) != PB_LTYPE_EXTENSION)
|
||||
{
|
||||
/* Found it */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} while (iter->index != start);
|
||||
|
||||
/* Searched all the way back to start, and found nothing. */
|
||||
(void)load_descriptor_values(iter);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool pb_field_iter_find_extension(pb_field_iter_t *iter)
|
||||
{
|
||||
if (PB_LTYPE(iter->type) == PB_LTYPE_EXTENSION)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pb_size_t start = iter->index;
|
||||
uint32_t fieldinfo;
|
||||
|
||||
do
|
||||
{
|
||||
/* Advance iterator but don't load values yet */
|
||||
advance_iterator(iter);
|
||||
|
||||
/* Do fast check for field type */
|
||||
fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
|
||||
|
||||
if (PB_LTYPE((fieldinfo >> 8) & 0xFF) == PB_LTYPE_EXTENSION)
|
||||
{
|
||||
return load_descriptor_values(iter);
|
||||
}
|
||||
} while (iter->index != start);
|
||||
|
||||
/* Searched all the way back to start, and found nothing. */
|
||||
(void)load_descriptor_values(iter);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void *pb_const_cast(const void *p)
|
||||
{
|
||||
/* Note: this casts away const, in order to use the common field iterator
|
||||
* logic for both encoding and decoding. The cast is done using union
|
||||
* to avoid spurious compiler warnings. */
|
||||
union {
|
||||
void *p1;
|
||||
const void *p2;
|
||||
} t;
|
||||
t.p2 = p;
|
||||
return t.p1;
|
||||
}
|
||||
|
||||
bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message)
|
||||
{
|
||||
return pb_field_iter_begin(iter, desc, pb_const_cast(message));
|
||||
}
|
||||
|
||||
bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension)
|
||||
{
|
||||
return pb_field_iter_begin_extension(iter, (pb_extension_t*)pb_const_cast(extension));
|
||||
}
|
||||
|
||||
bool pb_default_field_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field)
|
||||
{
|
||||
if (field->data_size == sizeof(pb_callback_t))
|
||||
{
|
||||
pb_callback_t *pCallback = (pb_callback_t*)field->pData;
|
||||
|
||||
if (pCallback != NULL)
|
||||
{
|
||||
if (istream != NULL && pCallback->funcs.decode != NULL)
|
||||
{
|
||||
return pCallback->funcs.decode(istream, field, &pCallback->arg);
|
||||
}
|
||||
|
||||
if (ostream != NULL && pCallback->funcs.encode != NULL)
|
||||
{
|
||||
return pCallback->funcs.encode(ostream, field, &pCallback->arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true; /* Success, but didn't do anything */
|
||||
|
||||
}
|
||||
|
||||
#ifdef PB_VALIDATE_UTF8
|
||||
|
||||
/* This function checks whether a string is valid UTF-8 text.
|
||||
*
|
||||
* Algorithm is adapted from https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c
|
||||
* Original copyright: Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/> 2005-03-30
|
||||
* Licensed under "Short code license", which allows use under MIT license or
|
||||
* any compatible with it.
|
||||
*/
|
||||
|
||||
bool pb_validate_utf8(const char *str)
|
||||
{
|
||||
const pb_byte_t *s = (const pb_byte_t*)str;
|
||||
while (*s)
|
||||
{
|
||||
if (*s < 0x80)
|
||||
{
|
||||
/* 0xxxxxxx */
|
||||
s++;
|
||||
}
|
||||
else if ((s[0] & 0xe0) == 0xc0)
|
||||
{
|
||||
/* 110XXXXx 10xxxxxx */
|
||||
if ((s[1] & 0xc0) != 0x80 ||
|
||||
(s[0] & 0xfe) == 0xc0) /* overlong? */
|
||||
return false;
|
||||
else
|
||||
s += 2;
|
||||
}
|
||||
else if ((s[0] & 0xf0) == 0xe0)
|
||||
{
|
||||
/* 1110XXXX 10Xxxxxx 10xxxxxx */
|
||||
if ((s[1] & 0xc0) != 0x80 ||
|
||||
(s[2] & 0xc0) != 0x80 ||
|
||||
(s[0] == 0xe0 && (s[1] & 0xe0) == 0x80) || /* overlong? */
|
||||
(s[0] == 0xed && (s[1] & 0xe0) == 0xa0) || /* surrogate? */
|
||||
(s[0] == 0xef && s[1] == 0xbf &&
|
||||
(s[2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */
|
||||
return false;
|
||||
else
|
||||
s += 3;
|
||||
}
|
||||
else if ((s[0] & 0xf8) == 0xf0)
|
||||
{
|
||||
/* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */
|
||||
if ((s[1] & 0xc0) != 0x80 ||
|
||||
(s[2] & 0xc0) != 0x80 ||
|
||||
(s[3] & 0xc0) != 0x80 ||
|
||||
(s[0] == 0xf0 && (s[1] & 0xf0) == 0x80) || /* overlong? */
|
||||
(s[0] == 0xf4 && s[1] > 0x8f) || s[0] > 0xf4) /* > U+10FFFF? */
|
||||
return false;
|
||||
else
|
||||
s += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
(void)pb_field_iter_next(iter);
|
||||
} while (iter->pos != start);
|
||||
|
||||
/* Searched all the way back to start, and found nothing. */
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -11,20 +11,18 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Iterator for pb_field_t list */
|
||||
struct pb_field_iter_s {
|
||||
const pb_field_t *start; /* Start of the pb_field_t array */
|
||||
const pb_field_t *pos; /* Current position of the iterator */
|
||||
unsigned required_field_index; /* Zero-based index that counts only the required fields */
|
||||
void *dest_struct; /* Pointer to start of the structure */
|
||||
void *pData; /* Pointer to current field value */
|
||||
void *pSize; /* Pointer to count/has field */
|
||||
};
|
||||
typedef struct pb_field_iter_s pb_field_iter_t;
|
||||
|
||||
/* Initialize the field iterator structure to beginning.
|
||||
* Returns false if the message type is empty. */
|
||||
bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_field_t *fields, void *dest_struct);
|
||||
bool pb_field_iter_begin(pb_field_iter_t *iter, const pb_msgdesc_t *desc, void *message);
|
||||
|
||||
/* Get a field iterator for extension field. */
|
||||
bool pb_field_iter_begin_extension(pb_field_iter_t *iter, pb_extension_t *extension);
|
||||
|
||||
/* Same as pb_field_iter_begin(), but for const message pointer.
|
||||
* Note that the pointers in pb_field_iter_t will be non-const but shouldn't
|
||||
* be written to when using these functions. */
|
||||
bool pb_field_iter_begin_const(pb_field_iter_t *iter, const pb_msgdesc_t *desc, const void *message);
|
||||
bool pb_field_iter_begin_extension_const(pb_field_iter_t *iter, const pb_extension_t *extension);
|
||||
|
||||
/* Advance the iterator to the next field.
|
||||
* Returns false when the iterator wraps back to the first field. */
|
||||
|
@ -34,6 +32,15 @@ bool pb_field_iter_next(pb_field_iter_t *iter);
|
|||
* Returns false if no such field exists. */
|
||||
bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag);
|
||||
|
||||
/* Find a field with type PB_LTYPE_EXTENSION, or return false if not found.
|
||||
* There can be only one extension range field per message. */
|
||||
bool pb_field_iter_find_extension(pb_field_iter_t *iter);
|
||||
|
||||
#ifdef PB_VALIDATE_UTF8
|
||||
/* Validate UTF-8 text string */
|
||||
bool pb_validate_utf8(const char *s);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -37,14 +37,31 @@ struct pb_istream_s
|
|||
bool (*callback)(pb_istream_t *stream, pb_byte_t *buf, size_t count);
|
||||
#endif
|
||||
|
||||
void *state; /* Free field for use by callback implementation */
|
||||
/* state is a free field for use of the callback function defined above.
|
||||
* Note that when pb_istream_from_buffer() is used, it reserves this field
|
||||
* for its own use.
|
||||
*/
|
||||
void *state;
|
||||
|
||||
/* Maximum number of bytes left in this stream. Callback can report
|
||||
* EOF before this limit is reached. Setting a limit is recommended
|
||||
* when decoding directly from file or network streams to avoid
|
||||
* denial-of-service by excessively long messages.
|
||||
*/
|
||||
size_t bytes_left;
|
||||
|
||||
#ifndef PB_NO_ERRMSG
|
||||
/* Pointer to constant (ROM) string when decoding function returns error */
|
||||
const char *errmsg;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifndef PB_NO_ERRMSG
|
||||
#define PB_ISTREAM_EMPTY {0,0,0,0}
|
||||
#else
|
||||
#define PB_ISTREAM_EMPTY {0,0,0}
|
||||
#endif
|
||||
|
||||
/***************************
|
||||
* Main decoding functions *
|
||||
***************************/
|
||||
|
@ -65,57 +82,61 @@ struct pb_istream_s
|
|||
* stream = pb_istream_from_buffer(buffer, count);
|
||||
* pb_decode(&stream, MyMessage_fields, &msg);
|
||||
*/
|
||||
bool pb_decode(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
bool pb_decode(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct);
|
||||
|
||||
/* Same as pb_decode, except does not initialize the destination structure
|
||||
* to default values. This is slightly faster if you need no default values
|
||||
* and just do memset(struct, 0, sizeof(struct)) yourself.
|
||||
/* Extended version of pb_decode, with several options to control
|
||||
* the decoding process:
|
||||
*
|
||||
* This can also be used for 'merging' two messages, i.e. update only the
|
||||
* fields that exist in the new message.
|
||||
* PB_DECODE_NOINIT: Do not initialize the fields to default values.
|
||||
* This is slightly faster if you do not need the default
|
||||
* values and instead initialize the structure to 0 using
|
||||
* e.g. memset(). This can also be used for merging two
|
||||
* messages, i.e. combine already existing data with new
|
||||
* values.
|
||||
*
|
||||
* Note: If this function returns with an error, it will not release any
|
||||
* dynamically allocated fields. You will need to call pb_release() yourself.
|
||||
*/
|
||||
bool pb_decode_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
|
||||
/* Same as pb_decode, except expects the stream to start with the message size
|
||||
* encoded as varint. Corresponds to parseDelimitedFrom() in Google's
|
||||
* PB_DECODE_DELIMITED: Input message starts with the message size as varint.
|
||||
* Corresponds to parseDelimitedFrom() in Google's
|
||||
* protobuf API.
|
||||
*/
|
||||
bool pb_decode_delimited(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
|
||||
/* Same as pb_decode_delimited, except that it does not initialize the destination structure.
|
||||
* See pb_decode_noinit
|
||||
*/
|
||||
bool pb_decode_delimited_noinit(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
|
||||
/* Same as pb_decode, except allows the message to be terminated with a null byte.
|
||||
* NOTE: Until nanopb-0.4.0, pb_decode() also allows null-termination. This behaviour
|
||||
* is not supported in most other protobuf implementations, so pb_decode_delimited()
|
||||
*
|
||||
* PB_DECODE_NULLTERMINATED: Stop reading when field tag is read as 0. This allows
|
||||
* reading null terminated messages.
|
||||
* NOTE: Until nanopb-0.4.0, pb_decode() also allows
|
||||
* null-termination. This behaviour is not supported in
|
||||
* most other protobuf implementations, so PB_DECODE_DELIMITED
|
||||
* is a better option for compatibility.
|
||||
*
|
||||
* Multiple flags can be combined with bitwise or (| operator)
|
||||
*/
|
||||
bool pb_decode_nullterminated(pb_istream_t *stream, const pb_field_t fields[], void *dest_struct);
|
||||
#define PB_DECODE_NOINIT 0x01U
|
||||
#define PB_DECODE_DELIMITED 0x02U
|
||||
#define PB_DECODE_NULLTERMINATED 0x04U
|
||||
bool pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags);
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define pb_decode_noinit(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_NOINIT)
|
||||
#define pb_decode_delimited(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_DELIMITED)
|
||||
#define pb_decode_delimited_noinit(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_DELIMITED | PB_DECODE_NOINIT)
|
||||
#define pb_decode_nullterminated(s,f,d) pb_decode_ex(s,f,d, PB_DECODE_NULLTERMINATED)
|
||||
|
||||
#ifdef PB_ENABLE_MALLOC
|
||||
/* Release any allocated pointer fields. If you use dynamic allocation, you should
|
||||
* call this for any successfully decoded message when you are done with it. If
|
||||
* pb_decode() returns with an error, the message is already released.
|
||||
*/
|
||||
void pb_release(const pb_field_t fields[], void *dest_struct);
|
||||
#endif
|
||||
|
||||
void pb_release(const pb_msgdesc_t *fields, void *dest_struct);
|
||||
|
||||
/**************************************
|
||||
* Functions for manipulating streams *
|
||||
**************************************/
|
||||
|
||||
/* Create an input stream for reading from a memory buffer.
|
||||
*
|
||||
* msglen should be the actual length of the message, not the full size of
|
||||
* allocated buffer.
|
||||
*
|
||||
* Alternatively, you can use a custom stream that reads directly from e.g.
|
||||
* a file or a network socket.
|
||||
*/
|
||||
pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize);
|
||||
pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t msglen);
|
||||
|
||||
/* Function to read from a pb_istream_t. You can use this if you need to
|
||||
* read some custom header data, or to read data in field callbacks.
|
||||
|
@ -167,6 +188,11 @@ bool pb_decode_fixed32(pb_istream_t *stream, void *dest);
|
|||
bool pb_decode_fixed64(pb_istream_t *stream, void *dest);
|
||||
#endif
|
||||
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
/* Decode a double value into float variable. */
|
||||
bool pb_decode_double_as_float(pb_istream_t *stream, float *dest);
|
||||
#endif
|
||||
|
||||
/* Make a limited-length substream for reading a PB_WT_STRING field. */
|
||||
bool pb_make_string_substream(pb_istream_t *stream, pb_istream_t *substream);
|
||||
bool pb_close_string_substream(pb_istream_t *stream, pb_istream_t *substream);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -33,15 +33,25 @@ struct pb_ostream_s
|
|||
* Also, NULL pointer marks a 'sizing stream' that does not
|
||||
* write anything.
|
||||
*/
|
||||
int *callback;
|
||||
const int *callback;
|
||||
#else
|
||||
bool (*callback)(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
|
||||
#endif
|
||||
void *state; /* Free field for use by callback implementation. */
|
||||
size_t max_size; /* Limit number of output bytes written (or use SIZE_MAX). */
|
||||
size_t bytes_written; /* Number of bytes written so far. */
|
||||
|
||||
/* state is a free field for use of the callback function defined above.
|
||||
* Note that when pb_ostream_from_buffer() is used, it reserves this field
|
||||
* for its own use.
|
||||
*/
|
||||
void *state;
|
||||
|
||||
/* Limit number of output bytes written. Can be set to SIZE_MAX. */
|
||||
size_t max_size;
|
||||
|
||||
/* Number of bytes written so far. */
|
||||
size_t bytes_written;
|
||||
|
||||
#ifndef PB_NO_ERRMSG
|
||||
/* Pointer to constant (ROM) string when decoding function returns error */
|
||||
const char *errmsg;
|
||||
#endif
|
||||
};
|
||||
|
@ -64,22 +74,31 @@ struct pb_ostream_s
|
|||
* stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
|
||||
* pb_encode(&stream, MyMessage_fields, &msg);
|
||||
*/
|
||||
bool pb_encode(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
bool pb_encode(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct);
|
||||
|
||||
/* Same as pb_encode, but prepends the length of the message as a varint.
|
||||
* Corresponds to writeDelimitedTo() in Google's protobuf API.
|
||||
*/
|
||||
bool pb_encode_delimited(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
|
||||
/* Same as pb_encode, but appends a null byte to the message for termination.
|
||||
* NOTE: This behaviour is not supported in most other protobuf implementations, so pb_encode_delimited()
|
||||
/* Extended version of pb_encode, with several options to control the
|
||||
* encoding process:
|
||||
*
|
||||
* PB_ENCODE_DELIMITED: Prepend the length of message as a varint.
|
||||
* Corresponds to writeDelimitedTo() in Google's
|
||||
* protobuf API.
|
||||
*
|
||||
* PB_ENCODE_NULLTERMINATED: Append a null byte to the message for termination.
|
||||
* NOTE: This behaviour is not supported in most other
|
||||
* protobuf implementations, so PB_ENCODE_DELIMITED
|
||||
* is a better option for compatibility.
|
||||
*/
|
||||
bool pb_encode_nullterminated(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
#define PB_ENCODE_DELIMITED 0x02U
|
||||
#define PB_ENCODE_NULLTERMINATED 0x04U
|
||||
bool pb_encode_ex(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct, unsigned int flags);
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define pb_encode_delimited(s,f,d) pb_encode_ex(s,f,d, PB_ENCODE_DELIMITED)
|
||||
#define pb_encode_nullterminated(s,f,d) pb_encode_ex(s,f,d, PB_ENCODE_NULLTERMINATED)
|
||||
|
||||
/* Encode the message to get the size of the encoded data, but do not store
|
||||
* the data. */
|
||||
bool pb_get_encoded_size(size_t *size, const pb_field_t fields[], const void *src_struct);
|
||||
bool pb_get_encoded_size(size_t *size, const pb_msgdesc_t *fields, const void *src_struct);
|
||||
|
||||
/**************************************
|
||||
* Functions for manipulating streams *
|
||||
|
@ -121,7 +140,7 @@ bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
|
|||
|
||||
/* Encode field header based on type and field number defined in the field
|
||||
* structure. Call this from the callback before writing out field contents. */
|
||||
bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_t *field);
|
||||
bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_iter_t *field);
|
||||
|
||||
/* Encode field header by manually specifying wire type. You need to use this
|
||||
* if you want to write out packed arrays from a callback field. */
|
||||
|
@ -156,12 +175,18 @@ bool pb_encode_fixed32(pb_ostream_t *stream, const void *value);
|
|||
bool pb_encode_fixed64(pb_ostream_t *stream, const void *value);
|
||||
#endif
|
||||
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
/* Encode a float value so that it appears like a double in the encoded
|
||||
* message. */
|
||||
bool pb_encode_float_as_double(pb_ostream_t *stream, float value);
|
||||
#endif
|
||||
|
||||
/* Encode a submessage field.
|
||||
* You need to pass the pb_field_t array and pointer to struct, just like
|
||||
* with pb_encode(). This internally encodes the submessage twice, first to
|
||||
* calculate message size and then to actually write it out.
|
||||
*/
|
||||
bool pb_encode_submessage(pb_ostream_t *stream, const pb_field_t fields[], const void *src_struct);
|
||||
bool pb_encode_submessage(pb_ostream_t *stream, const pb_msgdesc_t *fields, const void *src_struct);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
|
|
Loading…
Reference in New Issue