mirror of
https://codeberg.org/redict/redict.git
synced 2025-01-22 16:18:28 -05:00
Merge pull request #12409 from chayim/ck-hired120
Upgrade to hiredis 1.2.0.
This commit is contained in:
commit
9b1d4f003d
4
deps/README.md
vendored
4
deps/README.md
vendored
@ -63,6 +63,10 @@ Hiredis
|
|||||||
|
|
||||||
Hiredis is used by Sentinel, `redis-cli` and `redis-benchmark`. Like Redis, uses the SDS string library, but not necessarily the same version. In order to avoid conflicts, this version has all SDS identifiers prefixed by `hi`.
|
Hiredis is used by Sentinel, `redis-cli` and `redis-benchmark`. Like Redis, uses the SDS string library, but not necessarily the same version. In order to avoid conflicts, this version has all SDS identifiers prefixed by `hi`.
|
||||||
|
|
||||||
|
1. `git subtree pull --prefix deps/hiredis https://github.com/redis/hiredis.git <version-tag> --squash`<br>
|
||||||
|
This should hopefully merge the local changes into the new version.
|
||||||
|
2. Conflicts will arise (due to our changes) you'll need to resolve them and commit.
|
||||||
|
|
||||||
Linenoise
|
Linenoise
|
||||||
---
|
---
|
||||||
|
|
||||||
|
4
deps/hiredis/.github/workflows/build.yml
vendored
4
deps/hiredis/.github/workflows/build.yml
vendored
@ -133,8 +133,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
brew install openssl redis@6.2
|
brew install openssl redis@7.0
|
||||||
brew link redis@6.2 --force
|
brew link redis@7.0 --force
|
||||||
|
|
||||||
- name: Build hiredis
|
- name: Build hiredis
|
||||||
run: USE_SSL=1 make
|
run: USE_SSL=1 make
|
||||||
|
2
deps/hiredis/.github/workflows/test.yml
vendored
2
deps/hiredis/.github/workflows/test.yml
vendored
@ -60,7 +60,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Install qemu
|
- name: Install qemu
|
||||||
if: matrix.emulator
|
if: matrix.emulator
|
||||||
run: sudo apt-get install -y qemu-user
|
run: sudo apt-get update && sudo apt-get install -y qemu-user
|
||||||
- name: Install platform toolset
|
- name: Install platform toolset
|
||||||
if: matrix.toolset
|
if: matrix.toolset
|
||||||
run: sudo apt-get install -y gcc-${{matrix.toolset}}
|
run: sudo apt-get install -y gcc-${{matrix.toolset}}
|
||||||
|
51
deps/hiredis/CHANGELOG.md
vendored
51
deps/hiredis/CHANGELOG.md
vendored
@ -1,3 +1,54 @@
|
|||||||
|
## [1.2.0](https://github.com/redis/hiredis/tree/v1.2.0) - (2023-06-04)
|
||||||
|
|
||||||
|
Announcing Hiredis v1.2.0 with with new adapters, and a great many bug fixes.
|
||||||
|
|
||||||
|
## 🚀 New Features
|
||||||
|
|
||||||
|
- Add sdevent adapter @Oipo (#1144)
|
||||||
|
- Allow specifying the keepalive interval @michael-grunder (#1168)
|
||||||
|
- Add RedisModule adapter @tezc (#1182)
|
||||||
|
- Helper for setting TCP_USER_TIMEOUT socket option @zuiderkwast (#1188)
|
||||||
|
|
||||||
|
## 🐛 Bug Fixes
|
||||||
|
|
||||||
|
- Fix a typo in b6a052f. @yossigo (#1190)
|
||||||
|
- Fix wincrypt symbols conflict @hudayou (#1151)
|
||||||
|
- Don't attempt to set a timeout if we are in an error state. @michael-grunder (#1180)
|
||||||
|
- Accept -nan per the RESP3 spec recommendation. @michael-grunder (#1178)
|
||||||
|
- Fix colliding option values @zuiderkwast (#1172)
|
||||||
|
- Ensure functionality without `_MSC_VER` definition @windyakin (#1194)
|
||||||
|
|
||||||
|
## 🧰 Maintenance
|
||||||
|
|
||||||
|
- Add a test for the TCP_USER_TIMEOUT option. @michael-grunder (#1192)
|
||||||
|
- Add -Werror as a default. @yossigo (#1193)
|
||||||
|
- CI: Update homebrew Redis version. @yossigo (#1191)
|
||||||
|
- Fix typo in makefile. @michael-grunder (#1179)
|
||||||
|
- Write a version file for the CMake package @Neverlord (#1165)
|
||||||
|
- CMakeLists.txt: respect BUILD_SHARED_LIBS @ffontaine (#1147)
|
||||||
|
- Cmake static or shared @autoantwort (#1160)
|
||||||
|
- fix typo @tillkruss (#1153)
|
||||||
|
- Add a test ensuring we don't clobber connection error. @michael-grunder (#1181)
|
||||||
|
- Search for openssl on macOS @michael-grunder (#1169)
|
||||||
|
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
We'd like to thank all the contributors who worked on this release!
|
||||||
|
|
||||||
|
<a href="https://github.com/neverlord"><img src="https://github.com/neverlord.png" width="32" height="32"></a>
|
||||||
|
<a href="https://github.com/Oipo"><img src="https://github.com/Oipo.png" width="32" height="32"></a>
|
||||||
|
<a href="https://github.com/autoantwort"><img src="https://github.com/autoantwort.png" width="32" height="32"></a>
|
||||||
|
<a href="https://github.com/ffontaine"><img src="https://github.com/ffontaine.png" width="32" height="32"></a>
|
||||||
|
<a href="https://github.com/hudayou"><img src="https://github.com/hudayou.png" width="32" height="32"></a>
|
||||||
|
<a href="https://github.com/michael-grunder"><img src="https://github.com/michael-grunder.png" width="32" height="32"></a>
|
||||||
|
<a href="https://github.com/postgraph"><img src="https://github.com/postgraph.png" width="32" height="32"></a>
|
||||||
|
<a href="https://github.com/tezc"><img src="https://github.com/tezc.png" width="32" height="32"></a>
|
||||||
|
<a href="https://github.com/tillkruss"><img src="https://github.com/tillkruss.png" width="32" height="32"></a>
|
||||||
|
<a href="https://github.com/vityafx"><img src="https://github.com/vityafx.png" width="32" height="32"></a>
|
||||||
|
<a href="https://github.com/windyakin"><img src="https://github.com/windyakin.png" width="32" height="32"></a>
|
||||||
|
<a href="https://github.com/yossigo"><img src="https://github.com/yossigo.png" width="32" height="32"></a>
|
||||||
|
<a href="https://github.com/zuiderkwast"><img src="https://github.com/zuiderkwast.png" width="32" height="32"></a>
|
||||||
|
|
||||||
## [1.1.0](https://github.com/redis/hiredis/tree/v1.1.0) - (2022-11-15)
|
## [1.1.0](https://github.com/redis/hiredis/tree/v1.1.0) - (2022-11-15)
|
||||||
|
|
||||||
Announcing Hiredis v1.1.0 GA with better SSL convenience, new async adapters and a great many bug fixes.
|
Announcing Hiredis v1.1.0 GA with better SSL convenience, new async adapters and a great many bug fixes.
|
||||||
|
6
deps/hiredis/Makefile
vendored
6
deps/hiredis/Makefile
vendored
@ -39,7 +39,7 @@ export REDIS_TEST_CONFIG
|
|||||||
CC:=$(shell sh -c 'type $${CC%% *} >/dev/null 2>/dev/null && echo $(CC) || echo gcc')
|
CC:=$(shell sh -c 'type $${CC%% *} >/dev/null 2>/dev/null && echo $(CC) || echo gcc')
|
||||||
CXX:=$(shell sh -c 'type $${CXX%% *} >/dev/null 2>/dev/null && echo $(CXX) || echo g++')
|
CXX:=$(shell sh -c 'type $${CXX%% *} >/dev/null 2>/dev/null && echo $(CXX) || echo g++')
|
||||||
OPTIMIZATION?=-O3
|
OPTIMIZATION?=-O3
|
||||||
WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers
|
WARNINGS=-Wall -Wextra -Werror -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers
|
||||||
DEBUG_FLAGS?= -g -ggdb
|
DEBUG_FLAGS?= -g -ggdb
|
||||||
REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CPPFLAGS) $(CFLAGS) $(WARNINGS) $(DEBUG_FLAGS) $(PLATFORM_FLAGS)
|
REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CPPFLAGS) $(CFLAGS) $(WARNINGS) $(DEBUG_FLAGS) $(PLATFORM_FLAGS)
|
||||||
REAL_LDFLAGS=$(LDFLAGS)
|
REAL_LDFLAGS=$(LDFLAGS)
|
||||||
@ -311,7 +311,7 @@ install: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME) $(SSL_INSTALL)
|
|||||||
$(INSTALL) hiredis.h async.h read.h sds.h alloc.h sockcompat.h $(INSTALL_INCLUDE_PATH)
|
$(INSTALL) hiredis.h async.h read.h sds.h alloc.h sockcompat.h $(INSTALL_INCLUDE_PATH)
|
||||||
$(INSTALL) adapters/*.h $(INSTALL_INCLUDE_PATH)/adapters
|
$(INSTALL) adapters/*.h $(INSTALL_INCLUDE_PATH)/adapters
|
||||||
$(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME)
|
$(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME)
|
||||||
cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIBNAME)
|
cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIBNAME) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIB_MAJOR_NAME)
|
||||||
$(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH)
|
$(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH)
|
||||||
mkdir -p $(INSTALL_PKGCONF_PATH)
|
mkdir -p $(INSTALL_PKGCONF_PATH)
|
||||||
$(INSTALL) $(PKGCONFNAME) $(INSTALL_PKGCONF_PATH)
|
$(INSTALL) $(PKGCONFNAME) $(INSTALL_PKGCONF_PATH)
|
||||||
@ -320,7 +320,7 @@ install-ssl: $(SSL_DYLIBNAME) $(SSL_STLIBNAME) $(SSL_PKGCONFNAME)
|
|||||||
mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH)
|
mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH)
|
||||||
$(INSTALL) hiredis_ssl.h $(INSTALL_INCLUDE_PATH)
|
$(INSTALL) hiredis_ssl.h $(INSTALL_INCLUDE_PATH)
|
||||||
$(INSTALL) $(SSL_DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(SSL_DYLIB_MINOR_NAME)
|
$(INSTALL) $(SSL_DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(SSL_DYLIB_MINOR_NAME)
|
||||||
cd $(INSTALL_LIBRARY_PATH) && ln -sf $(SSL_DYLIB_MINOR_NAME) $(SSL_DYLIBNAME)
|
cd $(INSTALL_LIBRARY_PATH) && ln -sf $(SSL_DYLIB_MINOR_NAME) $(SSL_DYLIBNAME) && ln -sf $(SSL_DYLIB_MINOR_NAME) $(SSL_DYLIB_MAJOR_NAME)
|
||||||
$(INSTALL) $(SSL_STLIBNAME) $(INSTALL_LIBRARY_PATH)
|
$(INSTALL) $(SSL_STLIBNAME) $(INSTALL_LIBRARY_PATH)
|
||||||
mkdir -p $(INSTALL_PKGCONF_PATH)
|
mkdir -p $(INSTALL_PKGCONF_PATH)
|
||||||
$(INSTALL) $(SSL_PKGCONFNAME) $(INSTALL_PKGCONF_PATH)
|
$(INSTALL) $(SSL_PKGCONFNAME) $(INSTALL_PKGCONF_PATH)
|
||||||
|
4
deps/hiredis/hiredis.c
vendored
4
deps/hiredis/hiredis.c
vendored
@ -392,12 +392,12 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
|
|||||||
while (*_p != '\0' && strchr(flags,*_p) != NULL) _p++;
|
while (*_p != '\0' && strchr(flags,*_p) != NULL) _p++;
|
||||||
|
|
||||||
/* Field width */
|
/* Field width */
|
||||||
while (*_p != '\0' && isdigit(*_p)) _p++;
|
while (*_p != '\0' && isdigit((int) *_p)) _p++;
|
||||||
|
|
||||||
/* Precision */
|
/* Precision */
|
||||||
if (*_p == '.') {
|
if (*_p == '.') {
|
||||||
_p++;
|
_p++;
|
||||||
while (*_p != '\0' && isdigit(*_p)) _p++;
|
while (*_p != '\0' && isdigit((int) *_p)) _p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy va_list before consuming with va_arg */
|
/* Copy va_list before consuming with va_arg */
|
||||||
|
6
deps/hiredis/hiredis.h
vendored
6
deps/hiredis/hiredis.h
vendored
@ -46,9 +46,9 @@ typedef long long ssize_t;
|
|||||||
#include "alloc.h" /* for allocation wrappers */
|
#include "alloc.h" /* for allocation wrappers */
|
||||||
|
|
||||||
#define HIREDIS_MAJOR 1
|
#define HIREDIS_MAJOR 1
|
||||||
#define HIREDIS_MINOR 1
|
#define HIREDIS_MINOR 2
|
||||||
#define HIREDIS_PATCH 1
|
#define HIREDIS_PATCH 0
|
||||||
#define HIREDIS_SONAME 1.1.1-dev
|
#define HIREDIS_SONAME 1.1.0
|
||||||
|
|
||||||
/* Connection type can be blocking or non-blocking and is set in the
|
/* Connection type can be blocking or non-blocking and is set in the
|
||||||
* least significant bit of the flags field in redisContext. */
|
* least significant bit of the flags field in redisContext. */
|
||||||
|
1
deps/hiredis/net.c
vendored
1
deps/hiredis/net.c
vendored
@ -234,6 +234,7 @@ int redisContextSetTcpUserTimeout(redisContext *c, unsigned int timeout) {
|
|||||||
res = setsockopt(c->fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, sizeof(timeout));
|
res = setsockopt(c->fd, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout, sizeof(timeout));
|
||||||
#else
|
#else
|
||||||
res = -1;
|
res = -1;
|
||||||
|
errno = ENOTSUP;
|
||||||
(void)timeout;
|
(void)timeout;
|
||||||
#endif
|
#endif
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
|
10
deps/hiredis/sds.c
vendored
10
deps/hiredis/sds.c
vendored
@ -948,7 +948,7 @@ hisds *hi_sdssplitargs(const char *line, int *argc) {
|
|||||||
*argc = 0;
|
*argc = 0;
|
||||||
while(1) {
|
while(1) {
|
||||||
/* skip blanks */
|
/* skip blanks */
|
||||||
while(*p && isspace(*p)) p++;
|
while(*p && isspace((int) *p)) p++;
|
||||||
if (*p) {
|
if (*p) {
|
||||||
/* get a token */
|
/* get a token */
|
||||||
int inq=0; /* set to 1 if we are in "quotes" */
|
int inq=0; /* set to 1 if we are in "quotes" */
|
||||||
@ -959,8 +959,8 @@ hisds *hi_sdssplitargs(const char *line, int *argc) {
|
|||||||
while(!done) {
|
while(!done) {
|
||||||
if (inq) {
|
if (inq) {
|
||||||
if (*p == '\\' && *(p+1) == 'x' &&
|
if (*p == '\\' && *(p+1) == 'x' &&
|
||||||
isxdigit(*(p+2)) &&
|
isxdigit((int) *(p+2)) &&
|
||||||
isxdigit(*(p+3)))
|
isxdigit((int) *(p+3)))
|
||||||
{
|
{
|
||||||
unsigned char byte;
|
unsigned char byte;
|
||||||
|
|
||||||
@ -984,7 +984,7 @@ hisds *hi_sdssplitargs(const char *line, int *argc) {
|
|||||||
} else if (*p == '"') {
|
} else if (*p == '"') {
|
||||||
/* closing quote must be followed by a space or
|
/* closing quote must be followed by a space or
|
||||||
* nothing at all. */
|
* nothing at all. */
|
||||||
if (*(p+1) && !isspace(*(p+1))) goto err;
|
if (*(p+1) && !isspace((int) *(p+1))) goto err;
|
||||||
done=1;
|
done=1;
|
||||||
} else if (!*p) {
|
} else if (!*p) {
|
||||||
/* unterminated quotes */
|
/* unterminated quotes */
|
||||||
@ -999,7 +999,7 @@ hisds *hi_sdssplitargs(const char *line, int *argc) {
|
|||||||
} else if (*p == '\'') {
|
} else if (*p == '\'') {
|
||||||
/* closing quote must be followed by a space or
|
/* closing quote must be followed by a space or
|
||||||
* nothing at all. */
|
* nothing at all. */
|
||||||
if (*(p+1) && !isspace(*(p+1))) goto err;
|
if (*(p+1) && !isspace((int) *(p+1))) goto err;
|
||||||
done=1;
|
done=1;
|
||||||
} else if (!*p) {
|
} else if (!*p) {
|
||||||
/* unterminated quotes */
|
/* unterminated quotes */
|
||||||
|
20
deps/hiredis/ssl.c
vendored
20
deps/hiredis/ssl.c
vendored
@ -59,6 +59,8 @@
|
|||||||
#include "async_private.h"
|
#include "async_private.h"
|
||||||
#include "hiredis_ssl.h"
|
#include "hiredis_ssl.h"
|
||||||
|
|
||||||
|
#define OPENSSL_1_1_0 0x10100000L
|
||||||
|
|
||||||
void __redisSetError(redisContext *c, int type, const char *str);
|
void __redisSetError(redisContext *c, int type, const char *str);
|
||||||
|
|
||||||
struct redisSSLContext {
|
struct redisSSLContext {
|
||||||
@ -100,7 +102,7 @@ redisContextFuncs redisContextSSLFuncs;
|
|||||||
* Note that this is only required for OpenSSL < 1.1.0.
|
* Note that this is only required for OpenSSL < 1.1.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
#if OPENSSL_VERSION_NUMBER < OPENSSL_1_1_0
|
||||||
#define HIREDIS_USE_CRYPTO_LOCKS
|
#define HIREDIS_USE_CRYPTO_LOCKS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -256,13 +258,25 @@ redisSSLContext *redisCreateSSLContextWithOptions(redisSSLOptions *options, redi
|
|||||||
if (ctx == NULL)
|
if (ctx == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
ctx->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
|
const SSL_METHOD *ssl_method;
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= OPENSSL_1_1_0
|
||||||
|
ssl_method = TLS_client_method();
|
||||||
|
#else
|
||||||
|
ssl_method = SSLv23_client_method();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ctx->ssl_ctx = SSL_CTX_new(ssl_method);
|
||||||
if (!ctx->ssl_ctx) {
|
if (!ctx->ssl_ctx) {
|
||||||
if (error) *error = REDIS_SSL_CTX_CREATE_FAILED;
|
if (error) *error = REDIS_SSL_CTX_CREATE_FAILED;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
|
#if OPENSSL_VERSION_NUMBER >= OPENSSL_1_1_0
|
||||||
|
SSL_CTX_set_min_proto_version(ctx->ssl_ctx, TLS1_2_VERSION);
|
||||||
|
#else
|
||||||
|
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1);
|
||||||
|
#endif
|
||||||
|
|
||||||
SSL_CTX_set_verify(ctx->ssl_ctx, options->verify_mode, NULL);
|
SSL_CTX_set_verify(ctx->ssl_ctx, options->verify_mode, NULL);
|
||||||
|
|
||||||
if ((cert_filename != NULL && private_key_filename == NULL) ||
|
if ((cert_filename != NULL && private_key_filename == NULL) ||
|
||||||
|
16
deps/hiredis/test.c
vendored
16
deps/hiredis/test.c
vendored
@ -78,7 +78,7 @@ static int tests = 0, fails = 0, skips = 0;
|
|||||||
|
|
||||||
static void millisleep(int ms)
|
static void millisleep(int ms)
|
||||||
{
|
{
|
||||||
#if _MSC_VER
|
#ifdef _MSC_VER
|
||||||
Sleep(ms);
|
Sleep(ms);
|
||||||
#else
|
#else
|
||||||
usleep(ms*1000);
|
usleep(ms*1000);
|
||||||
@ -409,10 +409,19 @@ static void test_tcp_options(struct config cfg) {
|
|||||||
redisContext *c;
|
redisContext *c;
|
||||||
|
|
||||||
c = do_connect(cfg);
|
c = do_connect(cfg);
|
||||||
|
|
||||||
test("We can enable TCP_KEEPALIVE: ");
|
test("We can enable TCP_KEEPALIVE: ");
|
||||||
test_cond(redisEnableKeepAlive(c) == REDIS_OK);
|
test_cond(redisEnableKeepAlive(c) == REDIS_OK);
|
||||||
|
|
||||||
disconnect(c, 0);
|
#ifdef TCP_USER_TIMEOUT
|
||||||
|
test("We can set TCP_USER_TIMEOUT: ");
|
||||||
|
test_cond(redisSetTcpUserTimeout(c, 100) == REDIS_OK);
|
||||||
|
#else
|
||||||
|
test("Setting TCP_USER_TIMEOUT errors when unsupported: ");
|
||||||
|
test_cond(redisSetTcpUserTimeout(c, 100) == REDIS_ERR && c->err == REDIS_ERR_IO);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
redisFree(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_reply_reader(void) {
|
static void test_reply_reader(void) {
|
||||||
@ -1567,6 +1576,9 @@ static void test_throughput(struct config config) {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
#ifdef HIREDIS_TEST_ASYNC
|
#ifdef HIREDIS_TEST_ASYNC
|
||||||
|
|
||||||
|
#pragma GCC diagnostic ignored "-Woverlength-strings" /* required on gcc 4.8.x due to assert statements */
|
||||||
|
|
||||||
struct event_base *base;
|
struct event_base *base;
|
||||||
|
|
||||||
typedef struct TestState {
|
typedef struct TestState {
|
||||||
|
Loading…
Reference in New Issue
Block a user