Skip to content

Commit

Permalink
Secure tunnel WebSocket Protocol v3 Support (#84)
Browse files Browse the repository at this point in the history
* add support for Secure Tunnel WebSocket Protocol V3: https://github.com/aws-samples/aws-iot-securetunneling-localproxy/blob/main/V3WebSocketProtocolGuide.md

---------

Co-authored-by: Michael Graeb <[email protected]>
  • Loading branch information
sbSteveK and graebm authored Apr 19, 2023
1 parent 03c7ca4 commit 0f98a14
Show file tree
Hide file tree
Showing 12 changed files with 2,584 additions and 553 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
- 'main'

env:
BUILDER_VERSION: v0.9.26
BUILDER_VERSION: v0.9.40
BUILDER_SOURCE: releases
BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net
PACKAGE_NAME: aws-c-iot
Expand Down Expand Up @@ -105,12 +105,12 @@ jobs:
runs-on: windows-2019 # windows-2019 is last env with Visual Studio 2015 (v14.0) toolset
strategy:
matrix:
arch: [Win32, x64]
arch: [x86, x64]
steps:
- name: Build ${{ env.PACKAGE_NAME }} + consumers
run: |
python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')"
python builder.pyz build -p ${{ env.PACKAGE_NAME }} --cmake-extra=-Tv140 --cmake-extra=-A${{ matrix.arch }}
python builder.pyz build -p ${{ env.PACKAGE_NAME }} --target windows-${{ matrix.arch }} --compiler msvc-14
windows-shared-libs:
runs-on: windows-2022 # latest
Expand All @@ -128,8 +128,8 @@ jobs:
python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')"
chmod a+x builder
./builder build -p ${{ env.PACKAGE_NAME }}
# Test downstream repos.
# This should not be required because we can run into a chicken and egg problem if there is a change that needs some fix in a downstream repo.
downstream:
Expand Down
5 changes: 4 additions & 1 deletion include/aws/iotdevice/iotdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ enum aws_iotdevice_error {
AWS_ERROR_IOTDEVICE_DEFENDER_PUBLISH_FAILURE,
AWS_ERROR_IOTDEVICE_DEFENDER_UNKNOWN_TASK_STATUS,

AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_STREAM,
AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_STREAM_ID,
AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_CONNECTION_ID,
AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INVALID_SERVICE_ID,
AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_INCORRECT_MODE,
AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_BAD_SERVICE_ID,
AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DATA_OPTIONS_VALIDATION,
Expand All @@ -34,6 +36,7 @@ enum aws_iotdevice_error {
AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_OPERATION_FAILED_DUE_TO_OFFLINE_QUEUE_POLICY,
AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_UNEXPECTED_HANGUP,
AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_USER_REQUESTED_STOP,
AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_PROTOCOL_VERSION_MISSMATCH,
AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_TERMINATED,
AWS_ERROR_IOTDEVICE_SECURE_TUNNELING_DECODE_FAILURE,

Expand Down
53 changes: 47 additions & 6 deletions include/aws/iotdevice/private/secure_tunneling_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <aws/common/task_scheduler.h>
#include <aws/http/proxy.h>
#include <aws/http/websocket.h>
#include <aws/io/host_resolver.h>
#include <aws/io/socket.h>
#include <aws/io/tls_channel_handler.h>

Expand Down Expand Up @@ -99,10 +100,21 @@ struct data_tunnel_pair {
struct aws_allocator *allocator;
struct aws_byte_buf buf;
struct aws_byte_cursor cur;
enum aws_secure_tunnel_message_type type;
const struct aws_secure_tunnel *secure_tunnel;
bool length_prefix_written;
};

struct aws_secure_tunnel_message_storage {
struct aws_allocator *allocator;
struct aws_secure_tunnel_message_view storage_view;

struct aws_byte_cursor service_id;
struct aws_byte_cursor payload;

struct aws_byte_buf storage;
};

/*
* Secure tunnel configuration
*/
Expand All @@ -120,28 +132,42 @@ struct aws_secure_tunnel_options_storage {

struct aws_string *endpoint_host;

/* Stream related info */
int32_t stream_id;

struct aws_hash_table service_ids;

/* Callbacks */
aws_secure_tunnel_message_received_fn *on_message_received;
aws_secure_tunneling_on_connection_complete_fn *on_connection_complete;
aws_secure_tunneling_on_connection_shutdown_fn *on_connection_shutdown;
aws_secure_tunneling_on_stream_start_fn *on_stream_start;
aws_secure_tunneling_on_stream_reset_fn *on_stream_reset;
aws_secure_tunneling_on_connection_start_fn *on_connection_start;
aws_secure_tunneling_on_connection_reset_fn *on_connection_reset;
aws_secure_tunneling_on_session_reset_fn *on_session_reset;
aws_secure_tunneling_on_stopped_fn *on_stopped;
aws_secure_tunneling_on_send_message_complete_fn *on_send_message_complete;

aws_secure_tunneling_on_send_data_complete_fn *on_send_data_complete;
aws_secure_tunneling_on_termination_complete_fn *on_termination_complete;
void *secure_tunnel_on_termination_user_data;

void *user_data;
enum aws_secure_tunneling_local_proxy_mode local_proxy_mode;
};

struct aws_secure_tunnel_connections {
struct aws_allocator *allocator;

uint8_t protocol_version;

/* Used for streams not using multiplexing (service ids) */
int32_t stream_id;
struct aws_hash_table connection_ids;

/* Table containing streams using multiplexing (service ids) */
struct aws_hash_table service_ids;

/* Message used for initializing a stream upon a reconnect due to a protocol version missmatch */
struct aws_secure_tunnel_message_storage *restore_stream_message_view;
struct aws_secure_tunnel_message_storage restore_stream_message;
};

struct aws_secure_tunnel_vtable {
/* aws_high_res_clock_get_ticks */
uint64_t (*get_current_time_fn)(void);
Expand Down Expand Up @@ -175,9 +201,16 @@ struct aws_secure_tunnel {
*/
struct aws_secure_tunnel_options_storage *config;

/*
* Stores connection related information
*/
struct aws_secure_tunnel_connections *connections;

struct aws_tls_ctx *tls_ctx;
struct aws_tls_connection_options tls_con_opt;

struct aws_host_resolution_config host_resolution_config;

/*
* The recurrent task that runs all secure tunnel logic outside of external event callbacks. Bound to the secure
* tunnel's event loop.
Expand Down Expand Up @@ -267,6 +300,14 @@ AWS_IOTDEVICE_API void aws_secure_tunnel_set_vtable(
*/
AWS_IOTDEVICE_API const struct aws_secure_tunnel_vtable *aws_secure_tunnel_get_default_vtable(void);

/*
* For testing purposes. This message type should only be sent due to internal logic.
*/
AWS_IOTDEVICE_API
int aws_secure_tunnel_connection_reset(
struct aws_secure_tunnel *secure_tunnel,
const struct aws_secure_tunnel_message_view *message_options);

AWS_EXTERN_C_END

#endif /* AWS_IOTDEVICE_SECURE_TUNNELING_IMPL_H */
37 changes: 26 additions & 11 deletions include/aws/iotdevice/private/secure_tunneling_operations.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,22 @@ enum aws_secure_tunnel_operation_type {
AWS_STOT_PING,
AWS_STOT_MESSAGE,
AWS_STOT_STREAM_RESET,
AWS_STOT_STREAM_START
AWS_STOT_STREAM_START,
AWS_STOT_CONNECTION_START,
AWS_STOT_CONNECTION_RESET,
};

struct aws_service_id_element {
struct aws_allocator *allocator;
struct aws_byte_cursor service_id_cur;
struct aws_string *service_id_string;
int32_t stream_id;
struct aws_hash_table connection_ids;
};

struct aws_secure_tunnel_message_storage {
struct aws_connection_id_element {
struct aws_allocator *allocator;
struct aws_secure_tunnel_message_view storage_view;

bool ignorable;
int32_t stream_id;
struct aws_byte_cursor service_id;
struct aws_byte_cursor payload;

struct aws_byte_buf storage;
uint32_t connection_id;
};

/* Basic vtable for all secure tunnel operations. Implementations are per-message type */
Expand All @@ -57,10 +53,15 @@ struct aws_secure_tunnel_operation_vtable {
struct aws_secure_tunnel_operation *operation,
struct aws_secure_tunnel *secure_tunnel);

/* Set the stream id of outgoing st_msg to +1 of the currently set stream id */
/* Set the stream id of outgoing STREAM START message to +1 of the currently set stream id */
int (*aws_secure_tunnel_operation_set_next_stream_id_fn)(
struct aws_secure_tunnel_operation *operation,
struct aws_secure_tunnel *secure_tunnel);

/* Set the connection id of outbound CONNECTION START as active for the Source device */
int (*aws_secure_tunnel_operation_set_connection_start_id)(
struct aws_secure_tunnel_operation *operation,
struct aws_secure_tunnel *secure_tunnel);
};

/**
Expand Down Expand Up @@ -172,6 +173,12 @@ struct aws_secure_tunnel_options_storage *aws_secure_tunnel_options_storage_new(
struct aws_allocator *allocator,
const struct aws_secure_tunnel_options *options);

AWS_IOTDEVICE_API
void aws_secure_tunnel_connections_destroy(struct aws_secure_tunnel_connections *storage);

AWS_IOTDEVICE_API
struct aws_secure_tunnel_connections *aws_secure_tunnel_connections_new(struct aws_allocator *allocator);

AWS_IOTDEVICE_API
void aws_secure_tunnel_options_storage_log(
const struct aws_secure_tunnel_options_storage *options_storage,
Expand All @@ -197,6 +204,14 @@ struct aws_service_id_element *aws_service_id_element_new(
const struct aws_byte_cursor *service_id,
int32_t stream_id);

AWS_IOTDEVICE_API
void aws_connection_id_destroy(void *data);

AWS_IOTDEVICE_API
struct aws_connection_id_element *aws_connection_id_element_new(
struct aws_allocator *allocator,
uint32_t connection_id);

AWS_EXTERN_C_END

#endif /* AWS_IOTDEVICE_SECURE_TUNNELING_OPERATION_H */
5 changes: 1 addition & 4 deletions include/aws/iotdevice/private/serializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#define AWS_IOT_ST_MAXIMUM_1_BYTE_VARINT_VALUE 128
#define AWS_IOT_ST_MAXIMUM_2_BYTE_VARINT_VALUE 16384
#define AWS_IOT_ST_MAXIMUM_3_BYTE_VARINT_VALUE 2097152
#define AWS_IOT_ST_MAX_MESSAGE_SIZE (64 * 1024)
#define AWS_IOT_ST_MAX_PAYLOAD_SIZE (63 * 1024)

enum aws_secure_tunnel_field_number {
AWS_SECURE_TUNNEL_FN_TYPE = 1,
Expand Down Expand Up @@ -56,9 +56,6 @@ int aws_secure_tunnel_deserialize_message_from_cursor(
struct aws_byte_cursor *cursor,
aws_secure_tunnel_on_message_received_fn *on_message_received);

AWS_IOTDEVICE_API
const char *aws_secure_tunnel_message_type_to_c_string(enum aws_secure_tunnel_message_type message_type);

AWS_EXTERN_C_END

#endif
Loading

0 comments on commit 0f98a14

Please sign in to comment.