Skip to content

Commit

Permalink
Merge pull request #475 from atsign-foundation/feat-socket-layer
Browse files Browse the repository at this point in the history
feat: move mbedtls sockets into its own layer under connection
  • Loading branch information
XavierChanth authored Dec 19, 2024
2 parents 1bf6012 + e36b593 commit 247ac4b
Show file tree
Hide file tree
Showing 21 changed files with 852 additions and 407 deletions.
10 changes: 4 additions & 6 deletions examples/desktop/repl/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
* --key-file [~/.atsign/keys/@atsign_key.atKeys]
*/

static int set_up_pkam_auth_options(atclient_authenticate_options *pkam_authenticate_options,
const char *root_url);
static int set_up_pkam_auth_options(atclient_authenticate_options *pkam_authenticate_options, const char *root_url);
static int start_repl_loop(atclient *atclient, repl_args *repl_args);

int main(int argc, char *argv[]) {
Expand Down Expand Up @@ -97,8 +96,7 @@ exit: {
}
}

static int set_up_pkam_auth_options(atclient_authenticate_options *pkam_authenticate_options,
const char *root_url) {
static int set_up_pkam_auth_options(atclient_authenticate_options *pkam_authenticate_options, const char *root_url) {
int ret = 1;

if (pkam_authenticate_options == NULL) {
Expand Down Expand Up @@ -162,7 +160,7 @@ static int start_repl_loop(atclient *atclient, repl_args *repl_args) {

bool loop = true;

const size_t stdin_buffer_size = STDIN_BUFFER_SIZE;
size_t stdin_buffer_size = STDIN_BUFFER_SIZE;
char stdin_buffer[stdin_buffer_size];
char *stdin_buffer_ptr = stdin_buffer;
size_t stdin_buffer_len = 0;
Expand Down Expand Up @@ -202,7 +200,7 @@ static int start_repl_loop(atclient *atclient, repl_args *repl_args) {
goto exit;
}

if((ret = atclient_connection_read(&(atclient->atserver_connection), &recv, NULL, 0)) != 0) {
if ((ret = atclient_connection_read(&(atclient->atserver_connection), (unsigned char **)&recv, NULL)) != 0) {
atlogger_log(TAG, ATLOGGER_LOGGING_LEVEL_ERROR, "Failed to read response\n");
goto exit;
}
Expand Down
1 change: 1 addition & 0 deletions generators/arduino/atsdk/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ overrides() {
echo '#define PRIu64 "llu"'
echo "#define ATCHOPS_TARGET_ARDUINO"
echo "#define ATCHOPS_MBEDTLS_VERSION_2"
echo "#define ATCLIENT_NET_SOCKET_PROVIDER_EXTERNAL"
} >>$src_base/atchops/platform.h
}

Expand Down
2 changes: 0 additions & 2 deletions packages/atchops/include/atchops/platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@

// Platforms we support

// Default MbedTLS version

#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
#define ATCHOPS_TARGET_UNIX

Expand Down
2 changes: 2 additions & 0 deletions packages/atclient/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ set(
${CMAKE_CURRENT_LIST_DIR}/src/atnotification.c
${CMAKE_CURRENT_LIST_DIR}/src/connection_hooks.c
${CMAKE_CURRENT_LIST_DIR}/src/connection.c
${CMAKE_CURRENT_LIST_DIR}/src/socket.c
${CMAKE_CURRENT_LIST_DIR}/src/socket_mbedtls.c
${CMAKE_CURRENT_LIST_DIR}/src/encryption_key_helpers.c
${CMAKE_CURRENT_LIST_DIR}/src/metadata.c
${CMAKE_CURRENT_LIST_DIR}/src/monitor.c
Expand Down
37 changes: 21 additions & 16 deletions packages/atclient/include/atclient/connection.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
/*
*
* The connection family of types and methods represents a single connection to
* if you want a pure socket representation see socket.h.
*
* At the moment _socket represents a singular tcp socket, but in the future it may be altered
* to be a union of different connection types, such as a websocket or other construct.
* It is considered an internal construct and is subject to breaking changes across
* minor releases, especially while at_c remains in beta status.
*
*/
#ifndef ATCLIENT_CONNECTION_H
#define ATCLIENT_CONNECTION_H
#ifdef __cplusplus
extern "C" {
#endif

#include "atchops/mbedtls.h"
#include "atclient/connection_hooks.h"
#include <atchops/platform.h> // IWYU pragma: keep

#include "atclient/connection_hooks.h"
#include "atclient/socket.h"
#include <stdbool.h>
#include <stddef.h>

Expand All @@ -18,27 +30,21 @@ typedef enum atclient_connection_type {

typedef struct atclient_connection {
atclient_connection_type type; // set in atclient_connection_init

uint16_t port; // example: 64
bool _is_host_initialized : 1;
char *host; // example: "root.atsign.org"

bool _is_port_initialized : 1;
uint16_t port; // example: 64
bool _is_connection_enabled : 1;
bool _is_hooks_enabled : 1;

char *host; // example: "root.atsign.org"

// atclient_connection_connect sets this to true and atclient_connection_disconnect sets this to false
// this does not mean that the connection is still alive, it just means that the connection was established at least
// once, at some point, check atclient_connection_is_connected for a live status on the connection
// _is_connection_enabled also serves as an internal boolean to check if the following mbedlts contexts have been
// initialized and need to be freed at the end
bool _is_connection_enabled : 1;
mbedtls_net_context net;
mbedtls_ssl_context ssl;
mbedtls_ssl_config ssl_config;
mbedtls_x509_crt cacert;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;

bool _is_hooks_enabled : 1;
struct atclient_tls_socket _socket;
atclient_connection_hooks *hooks;
} atclient_connection;

Expand Down Expand Up @@ -80,8 +86,7 @@ int atclient_connection_connect(atclient_connection *ctx, const char *host, cons
* @param value_max_len the maximum length of the data to read, setting this to 0 means no limit
* @return int 0 on success
*/
int atclient_connection_read(atclient_connection *ctx, unsigned char **value, size_t *value_len,
const size_t value_max_len);
int atclient_connection_read(atclient_connection *ctx, unsigned char **value, size_t *value_len);

/**
* @brief Write data to the connection
Expand Down
5 changes: 1 addition & 4 deletions packages/atclient/include/atclient/mbedtls.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@
extern "C" {
#endif

#include <atchops/mbedtls.h> // IWYU pragma: export
#include <mbedtls/net_sockets.h> // IWYU pragma: export
#include <mbedtls/ssl.h> // IWYU pragma: export
#include <mbedtls/threading.h> // IWYU pragma: export
#include <atchops/mbedtls.h> // IWYU pragma: export

#ifdef __cplusplus
}
Expand Down
1 change: 1 addition & 0 deletions packages/atclient/include/atclient/monitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ extern "C" {

#include "atclient/atclient.h"
#include "atclient/atnotification.h"
#include "atclient/socket.h"
#include <atchops/platform.h> // IWYU pragma: keep
#include <stdbool.h>

Expand Down
135 changes: 135 additions & 0 deletions packages/atclient/include/atclient/socket.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#ifndef ATCLIENT_SOCKET_H
#define ATCLIENT_SOCKET_H
#include <atchops/platform.h>
#ifndef ATCLIENT_SOCKET_SHARED_H
#include <atclient/socket_shared.h>
#endif
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif

#ifndef ATCLIENT_SSL_TIMEOUT_EXITCODE

#if defined(ATCLIENT_SOCKET_PROVIDER_MBEDTLS)
#define ATCLIENT_SSL_TIMEOUT_EXITCODE MBEDTLS_ERR_SSL_TIMEOUT

#elif defined(ATCLIENT_SOCKET_PROVIDER_ARDUINO_BEARSSL)
// Most arduino libraries only use -1 or positive integers
#define ATCLIENT_SSL_TIMEOUT_EXITCODE -101

#else
#error "ATCLIENT_ERR_SSL_TIMEOUT is undefined"

#endif

#endif

// IWYU pragma: begin_exports

// Export the appropriate platform specific struct implementation
#if defined(ATCLIENT_SOCKET_PROVIDER_MBEDTLS)
#include "socket_mbedtls.h"
#endif

// IWYU pragma: end_exports

/**
* @brief Initializes a raw socket
*
* @param socket The socket structure to initialize
*/
void atclient_raw_socket_init(struct atclient_raw_socket *socket);

/**
* @brief Frees resources associated with a network socket
*
* @param socket The socket structure to free resources from
*/
void atclient_raw_socket_free(struct atclient_raw_socket *socket);

/**
* @brief Initializes a tls socket with the specified parameters
*
* @param socket The socket structure to initialize
*/
void atclient_tls_socket_init(struct atclient_tls_socket *socket);

/**
* @brief Configures the SSL on a TLS socket
*
* @param ca_pem The X.509 CA certificates in pem format (leave NULL to use the provided default certificates)
* @param ca_pem_len Length of the ca_pem, ignored if ca_pem is NULL
*
* @return 0 on success, non-zero on failure
*
* @note Should be called after atclient_tls_socket_init, note that this
* contains the rest of the initialization operations which have potential
* to fail
*/
int atclient_tls_socket_configure(struct atclient_tls_socket *socket, unsigned char *ca_pem, size_t ca_pem_len);

/**
* @brief Frees resources associated with a network socket
*
* @param socket The socket structure to free resources from
*/
void atclient_tls_socket_free(struct atclient_tls_socket *socket);

/**
* @brief Establishes a connection to the specified host and port using the network socket
*
* @param socket Pointer to the initialized network socket structure
* @param host The hostname or IP address to connect to
* @param port The port number to connect to
*
* @return 0 on success, non-zero on failure
*/
int atclient_tls_socket_connect(struct atclient_tls_socket *socket, const char *host, const uint16_t port);

/**
* @brief Disconnects and closes an established network socket connection
*
* @param socket Pointer to the network socket structure to disconnect
*
* @return 0 on success, non-zero on failure
*/
int atclient_tls_socket_disconnect(struct atclient_tls_socket *socket);

/**
* @brief Writes data to an established network socket connection
*
* @param socket Pointer to the network socket structure
* @param value Pointer to the buffer containing data to write
* @param value_len Length of the data to write in bytes
*
* @return 0 on success, non-zero on failure
*/
int atclient_tls_socket_write(struct atclient_tls_socket *socket, const unsigned char *value, size_t value_len);

/**
* @brief Reads data from an established network socket connection
*
* @param socket Pointer to the network socket structure
* @param value Pointer to the buffer where read data will be stored
* @param value_len Pointer to store the length of data read in bytes
* @param options Options which specify the behaviour of reading the data
*
* @return 0 on success, non-zero on failure
*/
int atclient_tls_socket_read(struct atclient_tls_socket *socket, unsigned char **value, size_t *value_len,
const struct atclient_socket_read_options options);

/**
* @brief Sets the read timeout for a TLS socket
*
* @param socket Pointer to the initialized TLS socket structure
* @param timeout_ms The timeout value in milliseconds
*/
void atclient_tls_socket_set_read_timeout(struct atclient_tls_socket *socket, const int timeout_ms);

#ifdef __cplusplus
}
#endif
#endif
34 changes: 34 additions & 0 deletions packages/atclient/include/atclient/socket_mbedtls.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// IWYU pragma: private, include "atclient/socket.h"
// IWYU pragma: friend "socket_mbedtls.*"
#ifndef ATCLIENT_SOCKET_MBEDTLS_H
#define ATCLIENT_SOCKET_MBEDTLS_H
#include <atchops/platform.h>
#if defined(ATCLIENT_SOCKET_PROVIDER_MBEDTLS)
#include <atclient/socket_shared.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
#include <mbedtls/net_sockets.h>
#include <mbedtls/ssl.h>
#include <mbedtls/threading.h>
#ifdef __cplusplus
extern "C" {
#endif

// TODO: Make this type more portable to consume later
struct atclient_raw_socket {
mbedtls_net_context net;
};

struct atclient_tls_socket {
struct atclient_raw_socket raw;
mbedtls_ssl_context ssl;
mbedtls_ssl_config ssl_config;
mbedtls_x509_crt cacert;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
};
#ifdef __cplusplus
}
#endif
#endif
#endif
69 changes: 69 additions & 0 deletions packages/atclient/include/atclient/socket_shared.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// IWYU pragma: private, include "atclient/socket.h"
// IWYU pragma: friend "socket_mbedtls.*"
#ifndef ATCLIENT_SOCKET_SHARED_H
#define ATCLIENT_SOCKET_SHARED_H
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif

#include <atchops/platform.h>

#if defined(ATCLIENT_SOCKET_PROVIDER_EXTERNAL)
// Noop, this indicates an external socket provider will be linked
#else
#define ATCLIENT_SOCKET_PROVIDER_MBEDTLS
#endif

#ifdef ATCLIENT_SOCKET_PROVIDER_EXTERNAL
#include "../atsdk_socket.h" // IWYU pragma: export
#else
// Defined later based on platform specific implementation
struct atclient_tls_socket;

// Raw socket is only implemented as an internal construct for now
// In the future it will be a supported standalone socket that can
// be used directly
struct atclient_raw_socket;
#endif

enum atclient_socket_read_type {
// ATCLIENT_SOCKET_READ_NUM_BYTES,
ATCLIENT_SOCKET_READ_UNTIL_CHAR,
ATCLIENT_SOCKET_READ_CLEAR_AT_PROMPT,
};

// Define how much we should try to read
struct atclient_socket_read_options {
enum atclient_socket_read_type type;
union {
// size_t num_bytes;
char until_char;
};
};

/**
* @brief Creates read options configured to read until a number of characters have been read
*
* @param bytes The number of characters to try to read
*
* @return struct atclient_socket_read_options Configuration structure for read operation
*/
// struct atclient_socket_read_options atclient_socket_read_num_bytes(size_t bytes);

/**
* @brief Creates read options configured to read until a specific character is encountered
*
* @param read_until The character to read until (delimiter)
*/
struct atclient_socket_read_options atclient_socket_read_until_char(char read_until);

/**
* @brief Creates read options configured to read until a specific character is encountered
*/
struct atclient_socket_read_options atclient_socket_read_clear_at_prompt();

#ifdef __cplusplus
}
#endif
#endif
Loading

0 comments on commit 247ac4b

Please sign in to comment.