/* utils.h
 *
 * Copyright (C) 2006-2026 wolfSSL Inc.
 *
 * This file is part of wolfSSL.
 *
 * wolfSSL is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * wolfSSL is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
 */

#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/ssl.h>
#include <wolfssl/test.h>

#ifndef TESTS_UTILS_H
#define TESTS_UTILS_H

#ifdef WOLFSSL_DUMP_MEMIO_STREAM
extern char tmpDirName[16];
extern const char* currentTestName;
#endif

/* Base dependencies for the manual memio test harness. The harness itself does
 * not require certificate support, so cert-less tests (e.g. PSK-only) can use
 * it through this narrower macro. */
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \
    (!defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13)) && defined(NO_CERTS)
#define HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES_NO_CERTS
#define HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES_BUILD
#endif

/* Full dependencies: the base harness plus certificate support. Most memio
 * tests set up a certificate-based handshake and must use this macro. */
#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_WOLFSSL_CLIENT) && \
    (!defined(WOLFSSL_NO_TLS12) || defined(WOLFSSL_TLS13)) && \
    !defined(NO_FILESYSTEM) && !defined(NO_CERTS) && \
    (!defined(NO_RSA) || defined(HAVE_RPK))
#define HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES
#define HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES_BUILD
#endif

#ifdef HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES_BUILD
#define TEST_MEMIO_BUF_SZ (64 * 1024)
#define TEST_MEMIO_MAX_MSGS 32

struct test_memio_ctx
{
    byte c_buff[TEST_MEMIO_BUF_SZ];
    int c_len;
    const char* c_ciphers;
    byte s_buff[TEST_MEMIO_BUF_SZ];
    int s_len;
    const char* s_ciphers;

    int c_force_want_write;
    int s_force_want_write;

    int c_msg_sizes[TEST_MEMIO_MAX_MSGS];
    int c_msg_count;
    int c_msg_pos;

    int s_msg_sizes[TEST_MEMIO_MAX_MSGS];
    int s_msg_count;
    int s_msg_pos;
};
int test_memio_write_cb(WOLFSSL *ssl, char *data, int sz, void *ctx);
int test_memio_read_cb(WOLFSSL *ssl, char *data, int sz, void *ctx);
int test_memio_do_handshake(WOLFSSL *ssl_c, WOLFSSL *ssl_s,
    int max_rounds, int *rounds);
int test_memio_setup(struct test_memio_ctx *ctx,
    WOLFSSL_CTX **ctx_c, WOLFSSL_CTX **ctx_s, WOLFSSL **ssl_c, WOLFSSL **ssl_s,
    method_provider method_c, method_provider method_s);
int test_memio_setup_ex(struct test_memio_ctx *ctx,
    WOLFSSL_CTX **ctx_c, WOLFSSL_CTX **ctx_s, WOLFSSL **ssl_c, WOLFSSL **ssl_s,
    method_provider method_c, method_provider method_s,
    byte *caCert, int caCertSz, byte *serverCert, int serverCertSz,
    byte *serverKey, int serverKeySz);
void test_memio_simulate_want_write(struct test_memio_ctx *ctx, int is_client,
        int enable);
void test_memio_clear_buffer(struct test_memio_ctx *ctx, int is_client);
int test_memio_inject_message(struct test_memio_ctx *ctx, int client, const char *data, int sz);
int test_memio_copy_message(const struct test_memio_ctx *ctx, int client,
        char *out, int *out_sz, int msg_pos);
int test_memio_get_message(const struct test_memio_ctx *ctx, int client,
        const char **out, int *out_sz, int msg_pos);
int test_memio_msg_is_hello_retry_request(const struct test_memio_ctx *ctx);
int test_memio_move_message(struct test_memio_ctx *ctx, int client,
        int msg_pos_in, int msg_pos_out);
int test_memio_drop_message(struct test_memio_ctx *ctx, int client, int msg_pos);
int test_memio_modify_message_len(struct test_memio_ctx *ctx, int client, int msg_pos, int new_len);
int test_memio_remove_from_buffer(struct test_memio_ctx *ctx, int client, int off, int sz);
#endif /* HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES_BUILD */

/* Shared TLS server/client thread bodies, defined in tests/api.c. The
 * definitions are gated on ENABLE_TLS_CALLBACK_TEST (a composite condition
 * locally #defined inside api.c) or (WOLFSSL_DTLS && WOLFSSL_SESSION_EXPORT).
 * Declared unconditionally here so api.c itself sees the prototype regardless
 * of which side of the local #define triggers; absent the definition the
 * prototypes are harmless and any caller would get a link error. */
THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args);
void run_wolfssl_client(void* args);

#if !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \
    defined(DEBUG_UNIT_TEST_CERTS)
void DEBUG_WRITE_CERT_X509(WOLFSSL_X509* x509, const char* fileName);
void DEBUG_WRITE_DER(const byte* der, int derSz, const char* fileName);
#else
#define DEBUG_WRITE_CERT_X509(x509, fileName) WC_DO_NOTHING
#define DEBUG_WRITE_DER(der, derSz, fileName) WC_DO_NOTHING
#endif

#endif /* TESTS_UTILS_H */
