Git Product home page Git Product logo

aws-c-io's Introduction

AWS-C-IO

This is a module for the AWS SDK for C. It handles all IO and TLS work for application protocols.

aws-c-io is an event driven framework for implementing application protocols. It is built on top of cross-platform abstractions that allow you as a developer to think only about the state machine and API for your protocols. A typical use-case would be to write something like Http on top of asynchronous-io with TLS already baked in. All of the platform and security concerns are already handled for you.

It is designed to be light-weight, fast, portable, and flexible for multiple domain use-cases such as: embedded, server, client, and mobile.

License

This library is licensed under the Apache 2.0 License.

Usage

Building

CMake 3.1+ is required to build.

<install-path> must be an absolute path in the following instructions.

Linux-Only Dependencies

If you are building on Linux, you will need to build aws-lc and s2n-tls first.

git clone [email protected]:awslabs/aws-lc.git
cmake -S aws-lc -B aws-lc/build -DCMAKE_INSTALL_PREFIX=<install-path>
cmake --build aws-lc/build --target install

git clone [email protected]:aws/s2n-tls.git
cmake -S s2n-tls -B s2n-tls/build -DCMAKE_INSTALL_PREFIX=<install-path> -DCMAKE_PREFIX_PATH=<install-path>
cmake --build s2n-tls/build --target install

Building aws-c-io and Remaining Dependencies

git clone [email protected]:awslabs/aws-c-common.git
cmake -S aws-c-common -B aws-c-common/build -DCMAKE_INSTALL_PREFIX=<install-path>
cmake --build aws-c-common/build --target install

git clone [email protected]:awslabs/aws-c-cal.git
cmake -S aws-c-cal -B aws-c-cal/build -DCMAKE_INSTALL_PREFIX=<install-path> -DCMAKE_PREFIX_PATH=<install-path>
cmake --build aws-c-cal/build --target install

git clone [email protected]:awslabs/aws-c-io.git
cmake -S aws-c-io -B aws-c-io/build -DCMAKE_INSTALL_PREFIX=<install-path> -DCMAKE_PREFIX_PATH=<install-path>
cmake --build aws-c-io/build --target install

Usage Patterns

This library contains many primitive building blocks that can be configured in a myriad of ways. However, most likely you simply need to use the aws_event_loop_group and aws_channel_bootstrap APIs.

Typical Client API Usage Pattern:

    /* setup */
    aws_io_library_init(allocator);

    struct aws_event_loop_group el_group;

    if (aws_event_loop_group_init_default(&el_group, allocator)) {
        goto cleanup;
    }

    struct aws_tls_ctx_options tls_options = { ... };
    struct aws_tls_ctx *tls_ctx = aws_tls_client_ctx_new(allocator, &tls_options);

    struct aws_tls_connection_options tls_client_conn_options = { ... };

    struct aws_client_bootstrap client_bootstrap;

    if (aws_client_bootstrap_init(&client_bootstrap, allocator, &el_group) {
        goto cleanup;
    }

    aws_client_bootstrap_set_tls_ctx(&client_bootstrap, tls_ctx);
    aws_client_bootstrap_set_alpn_callback(&client_bootstrap, your_alpn_callback);

    /* throughout your application's lifetime */
    struct aws_socket_options sock_options = { ... };
    struct aws_socket_endpoint endpoint = { ... };

    if (aws_client_bootstrap_new_tls_socket_channel(&client_bootstrap, &endpoint, &sock_options, &tls_options,
            your_channel_setup_callback, your_channel_shutdown_callback, your_context_data) {
        goto cleanup;
    }

    /* shutdown */
    aws_client_bootstrap_clean_up(&client_bootstrap);
    aws_tls_client_ctx_destroy(tls_ctx);
    aws_event_loop_group_clean_up(&el_group);
    aws_io_library_clean_up();

Typical Server API Usage Pattern:

    /* setup */
    aws_io_library_init(allocator);

    struct aws_event_loop_group el_group;

    if (aws_event_loop_group_init_default(&el_group, allocator)) {
        goto cleanup;
    }

    struct aws_tls_ctx_options tls_options = { ... };
    struct aws_tls_ctx *tls_ctx = aws_tls_server_ctx_new(allocator, &tls_options);

    struct aws_tls_connection_options tls_server_conn_options = { ... };

    struct aws_socket_options sock_options = { ... };
    struct aws_socket_endpoint endpoint = { ... };

    struct aws_server_bootstrap server_bootstrap;

    if (aws_server_bootstrap_init(&server_bootstrap, allocator, &el_group) {
        goto cleanup;
    }

    aws_server_bootstrap_set_tls_ctx(&server_bootstrap, tls_ctx);
    aws_server_bootstrap_set_alpn_callback(&server_bootstrap, your_alpn_callback);

    struct aws_socket *listener = aws_server_bootstrap_add_tls_socket_listener(&server_bootstrap, &endpoint, &sock_options, &tls_options,
                                                  your_incoming_channel_callback, your_channel_shutdown_callback, your_context_data);

    if (!listener) {
        goto cleanup;
    }


    /* shutdown */
    aws_server_bootstrap_remove_socket_listener(listener);
    aws_server_bootstrap_clean_up(&server_bootstrap);
    aws_tls_server_ctx_destroy(tls_ctx);
    aws_event_loop_group_clean_up(&el_group);
    aws_io_library_clean_up();

If you are building a protocol on top of sockets without the use of TLS, you can still use this pattern as your starting point. Simply call the aws_client_bootstrap_new_socket_channel aws_server_bootstrap_add_socket_listener respectively: instead of the TLS variants.

Concepts

Event Loop

Core to Async-IO is the event-loop. We provide an implementation for most platforms out of the box:

Platform Implementation
Linux Edge-Triggered Epoll
BSD Variants and Apple Devices KQueue
Windows IOCP (IO Completion Ports)

Also, you can always implement your own as well.

An Event Loop has a few jobs.

  1. Notify subscribers of IO Events
  2. Execute and maintain a task scheduler
  3. Maintain an opaque data store for consumers

The threading model for a channel (see below) is pinned to the thread of the event-loop. Each event-loop implementation provides an API to move a cross-thread call into the event-loop thread if necessary.

Channels and Slots

A channel is simply a container that drives the slots. It is responsible for providing an interface between slots and the underlying event-loop as well as invoking the slots to pass messages. As a channel runs. It also provides utilities for making sure slots and their handlers run in the correct thread and moving execution to that thread if necessary.

Channels and Slots Diagram

In this diagram, a channel is a collection of slots, and it knows how to make them communicate. It also controls the lifetime of slots.

When a channel is being shutdown, it will issue shutdown_direction messages in the appropriate direction. If it is in the read direction, it will call shutdown_direction on the first slot. Conversely, in the write direction, it will call shutdown_direction on the last slot in the channel. When all slots have successfully shutdown, the channel can be safely cleaned up and de-allocated.

Slots

Slots Diagram

Slots maintain their links to adjacent slots in the channel. So as the channel is processed, each slot will read from its left-adjacent slot, send those messages to the handler, and call their right-adjacent slot when it needs to send a message. Conversely, each slot will read from its right-adjacent slot, send those messages to the handler, and send messages to the left-adjacent slot in the channel. Most importantly, slots contain a reference to a handler. Handlers are responsible for doing most of the work (see below). Finally, slots have utilities for manipulating the connections of the slots themselves.

Slots can also be added, removed, or replaced dynamically from a channel.

Channel Handlers

The channel handler is the fundamental unit that protocol developers will implement. It contains all of your state machinery, framing, and optionally end-user APIs.

Handler Diagram

Special, pre-defined handlers

Out of the box you get a few handlers pre-implemented.

  1. Sockets. We've done the heavy lifting of implementing a consistent sockets interface for each platform. Sockets interact directly with the underlying io and are invoked directly by the event-loop for io events.
  2. Pipes (or something like them depending on platform), these are particularly useful for testing.
  3. TLS. We provide TLS implementations for most platforms.
Platform Implementation
Linux Signal-to-noise (s2n) see: https://github.com/aws/s2n-tls
BSD Variants s2n
Apple Devices Security Framework/ Secure Transport. See https://developer.apple.com/documentation/security/secure_transport
Windows Secure Channel. See https://msdn.microsoft.com/en-us/library/windows/desktop/aa380123(v=vs.85).aspx

In addition, you can always write your own handler around your favorite implementation and use that. To provide your own TLS implementation, you must build this library with the cmake argument -DBYO_CRYPTO=ON. You will no longer need s2n or libcrypto once you do this. Instead, your application provides an implementation of aws_tls_ctx, and aws_channel_handler. At startup time, you must invoke the functions: aws_tls_byo_crypto_set_client_setup_options() and aws_tls_byo_crypto_set_server_setup_options().

Typical Channel

Typical Channel Diagram

A typical channel will contain a socket handler, which receives io events from the event-loop. It will read up to 16 kb and pass the data to the next handler. The next handler is typically feeding a TLS implementation (see the above section on pre-defined handlers). The TLS handler will then pass the data to an application protocol. The application protocol could then expose an API to an application. When the application wants to send data, the whole process runs in reverse.

Channels can be much more complex though. For example, there could be nested channels for multiplexing/de-multiplexing, or there could be more handlers to cut down on handler complexity.

Note however, that a channel is always pinned to a single thread. It provides utilities for applications and handlers to move a task into that thread, but it is very important that handlers and application users of your handlers never block.

Channel IO Operation Fairness

Since multiple channels run in the same event-loop, we need to make sure channels are not starved by other active channels. To address this, the handlers consuming IO events from the event-loop should determine the appropriate max read and write and context switch before continuing. A context switch is performed, simply by scheduling a task to run at the current timestamp, to continue the IO operation.

A reasonable default is 16kb, but a savvy implementation may want to upgrade a few connections to 256kb if they notice a particularly fast connection (e.g. you notice EAGAIN or EWOULDBLOCK is never returned from write() calls).

Read Back Pressure

One of the most challenging aspects of asynchronous io programming, is managing when back-pressure should be applied to the underlying io layer. In the read direction, this is managed via update_window messages. Let's look at the below diagram for an example of how this works.

In this example, we have a channel setup with an event-loop which manages io event notifications. The first slot contains a socket handler. The socket handler will read directly from the socket. The second slot has a TLS handler. Its only job is to encrypt/decrypt the data passed to it and pass it back to the channel. The third and final slot contains the actual application protocol handler (could be Http, SIP, RTP it doesn't really matter).

The application protocol exposes an API to the application. As data is processed, we don't want to endlessly read, allocate, and process data faster than the application can use it. As a result, it has a 20kb window.

Read Back Pressure Diagram

  1. The event-loop notifies the socket handler that it has data available to read. The handler knows it can read up to 20kb so it reads a full 16kb from the socket and passes it to the next slot. Since the socket sees that there is still an open window, it, schedules a task to read again after the other channels have had a chance to process their pending reads.

    Likewise, the TLS handler decrypts the data and passes it to the slot containing the application protocol.

    The application protocol processes the 16 kb and hands it off to the application. At this point, the application hasn't notified the channel it is finished with the data (suppose application queues it), so the new window for the slot is 4 kb.

  2. The event-loop runs the scheduled read task from (1) after processing the other channels. The socket handler sees it can read 4kb more of data. Even though it can read 16kb at a time, to honor the window, it reads 4kb and passes it on. This time however, the window is 0, so the socket does not schedule another read task.

    The TLS handler decrypts the data and passes it on

    The application protocol reads 4kb, passes it to the application and its window is 0kb.

    The channel now goes idle waiting on the application to finish processing its data.

  3. The application notifies the channel (via the API on the application protocol handler) it has processed 20kb of data. This causes the protocol handler to issue an update_window message with an update of 20kb.

    Slot 2 passes the message on to the TLS handler. It evaluates the message and simply, sends a 20kb window update message to its slot.

    The socket handler receives the update_window message and schedules a new read task.

  4. The event-loop runs the scheduled read task from (3). The socket reads on the io-handle, but it returns EAGAIN or EWOULD_BLOCK. The channel now goes back to an idle state waiting on the event-loop to notify it that the socket is readable.

Write Back Pressure

Write back pressure comes into play when the application can produce data more quickly than it can be sent to the underlying io. To manage this, messages have members to attach a promise fn and context data to. When a handler exposes an API, it has the responsibility to take a fn and data from the user if over write is a possibility. The io-handler will invoke the promise after it has successfully written the last byte to the underlying io.

Thread Safety

In general, the plan for addressing thread-safety is to not share memory across threads. This library is designed around single threaded event-loops which process one or more channels. Anywhere a handler or channel exposes a back-channel API, it is responsible for checking which thread it was invoked from. If it is invoked from the event-loop's thread, then it may proceed as planned. If it is not, it is required to queue a task to do the work. When the task is executed, it will be executed in the correct thread.

The functions we specify as thread-safe, we do so because those functions are necessary for abiding by the stated threading model. For example, since scheduling a task is the main function for addressing cross-threaded operations, it has to be thread-safe.

Terminology

We use a few terms in the following sections that are not necessarily "C concepts". We assume you know C, but here are some definitions that may be helpful.

Run-time Polymorphic

This means that the API is driven by a virtual-table. This is simply a struct of function pointers. They are invoked via a c extern style API, but ultimately those public functions simply invoke the corresponding function in the v-table.

These are reserved for types that: a.) Need to be configurable, changable at runtime b.) Do not have immediate performance concerns caused by an indirect function call.

Compile-time Polymorphic

This means that the API is not necessarily driven by a virtual-table. It is exposed as a c extern style API, but the build system makes a decision about which symbols to compile based on factors such as platform and compile-time flags.

These are reserved for types that: a.) Need to be configurable at compile-time based on platform or compile-time options. b.) Have performance concerns caused by an indirect function call.

Note: that runtime configurability may still be something we need to expose here. In that case, a compiler flag will be used to denote that we are using a custom implementation for x feature. Then we will expose an implementation that indirectly invokes from a v-table and provides hooks for the application to plug into at runtime.

Promise, Promise Context

There are many phrases for this, callback, baton, event-handler etc... The key idea is that APIs that need to notify a caller when an asynchronous action is completed, should take a callback function and a pointer to an opaque object and invoke it upon completion. This term doesn't refer to the layout of the data. A promise in some instances may be a collection of functions in a structure. It's simply the language we use for the concept.

API

Note: unless otherwise stated,

  • no functions in this API are allowed to block.
  • nothing is thread-safe unless explicitly stated.

Event Loop

Event Loops are run-time polymorphic. We provide some implementations out of the box and a way to get an implementation without having to call a different function per platform. However, you can also create your own implementation and use it on any API that takes an event-loop as a parameter.

From a design perspective, the event-loop is not aware of channels or any of its handlers. It interacts with other entities only via its API.

Layout

struct aws_event_loop {
    struct aws_event_loop_vtable vtable;
    aws_clock clock;
    struct aws_allocator *allocator;
    struct aws_common_hash_table local_storage;
    void *impl_data;
};

V-Table

struct aws_event_loop_vtable {
    void (*destroy)(struct aws_event_loop *);
    int (*run) (struct aws_event_loop *);
    int (*stop) (struct aws_event_loop *, void (*on_stopped) (struct aws_event_loop *, void *), void *promise_user_data);
    int (*schedule_task) (struct aws_event_loop *, struct aws_task *task, uint64_t run_at);
    int (*subscribe_to_io_events) (struct aws_event_loop *, struct aws_io_handle *, int events,
        void(*on_event)(struct aws_event_loop *, struct aws_io_handle *, void *), void *user_data);
    int (*unsubscribe_from_io_events) (struct aws_event_loop *, struct aws_io_handle *);
    BOOL (*is_on_callers_thread) (struct aws_event_loop *);
};

Every implementation of aws_event_loop must implement this table. Let's look at some details for what each entry does.

void (*destroy)(struct aws_event_loop *);

This function is invoked when the event-loop is finished processing and is ready to be cleaned up and deallocated.

int (*run) (struct aws_event_loop *);

This function starts the running of the event-loop and then immediately returns. This could kick off a thread, or setup some resources to run and receive events in a back channel API. For example, you could have an epoll loop that runs in a thread, or you could have an event-loop pumped by a system loop such as glib, or libevent etc... and then publish events to your event-loop implementation.

int (*stop) (struct aws_event_loop *,
 void (*on_stopped) (struct aws_event_loop *, void *), void *promise_user_data);

The stop function signals the event-loop to shutdown. This function should not block but it should remove active io handles from the currently monitored or polled set and should begin notifying current subscribers via the on_event callback that the handle was removed._ Once the event-loop has shutdown to a safe state, it should invoke the on_stopped function.

int (*schedule_task) (struct aws_event_loop *, struct aws_task *task, uint64_t run_at);

This function schedules a task to run in its task scheduler at the time specified by run_at. Each event-loop is responsible for implementing a task scheduler. This function must not block, and must be thread-safe. How this is implemented will depend on platform. For example, one reasonable implementation is if the call comes from the event-loop's thread, to queue it in the task scheduler directly. Otherwise, write to a pipe that the event-loop is listening for events on. Upon noticing the write to the pipe, it can read the task from the pipe and schedule the task.

task must be copied.

run_at is using the system RAW_MONOTONIC clock (or the closest thing to it for that platform). It is represented as nanos since unix epoch.

int (*subscribe_to_io_events) (struct aws_event_loop *, struct aws_io_handle *, int events,
        void(*on_event)(struct aws_event_loop *, struct aws_io_handle *, int events, void *), void *user_data);

A subscriber will call this function to register an io_handle for event monitoring. This function is thread-safe.

events is a bit field of the events the subscriber wants to receive. A few events will always be registered (regardless of the value passed here), such as AWS_IO_EVENT_HANDLE_REMOVED. The event-loop will invoke on_event anytime it receives one or more of the registered events.

NOTE: The event-loop is not responsible for manipulating or setting io flags on io_handles. It will never call, read(), write(), connect(), accept(), close() etc... on any io handle it does not explicitly own. It is the subscriber's responsibility to know how to respond to the event.

NOTE: The event-loop will not maintain any state other than the io handles it is polling. So, for example, in edge-triggered epoll, it does not maintain a read ready list. It is the subscriber's responsibility to know it has more data to read or write and to schedule its tasks appropriately.

int (*unsubscribe_from_io_events) (struct aws_event_loop *, struct aws_io_handle *);

A subscriber will call this function to remove its io handle from the monitored events. For example, it would may this immediately before calling close() on a socket or pipe. on_event will still be invoked with AWS_IO_EVENT_HANDLE_REMOVED when this occurs.

BOOL (*is_on_callers_thread) (struct aws_event_loop *);

Returns TRUE if the caller is on the same thread as the event-loop. Returns FALSE otherwise. This allows users of the event-loop to make a decision about whether it is safe to interact with the loop directly, or if they need to schedule a task to run in the correct thread. This function is thread-safe.

API

int aws_event_loop_init_base (struct aws_allocator *, aws_clock clock, ...);

Initializes common data for all event-loops regardless of implementation. All implementations must call this function before returning from their allocation function.

struct aws_event_loop *aws_event_loop_new_default (struct aws_allocator *, aws_clock clock, ...);

Allocates and initializes the default event-loop implementation for the current platform. Calls aws_event_loop_init_base before returning.

struct aws_event_loop *aws_event_loop_destroy (struct aws_event_loop *);

Cleans up internal state of the event-loop implementation, and then calls the v-table destroy function.

int aws_event_loop_fetch_local_object ( struct aws_event_loop *, void *key, void **item);

All event-loops contain local storage for all users of the event-loop to store common data into. This function is for fetching one of those objects by key. The key for this store is of type void *. This function is NOT thread safe, and it expects the caller to be calling from the event-loop's thread. If this is not the case, the caller must first schedule a task on the event-loop to enter the correct thread.

int aws_event_loop_put_local_object ( struct aws_event_loop *, void *key, void *item);

All event-loops contain local storage for all users of the event-loop to store common data into. This function is for putting one of those objects by key. The key for this store is of type size_t. This function is NOT thread safe, and it expects the caller to be calling from the event-loop's thread. If this is not the case, the caller must first schedule a task on the event-loop to enter the correct thread.

int aws_event_loop_remove_local_object ( struct aws_event_loop *, void *key, void **item);

All event loops contain local storage for all users of the event loop to store common data into. This function is for removing one of those objects by key. The key for this store is of type void *. This function is NOT thread safe, and it expects the caller to be calling from the event loop's thread. If this is not the case, the caller must first schedule a task on the event loop to enter the correct thread. If found, and item is not NULL, the removed item is moved to item. It is the removers responsibility to free the memory pointed to by item. If it is NULL, the default deallocation strategy for the event loop will be used.

int aws_event_loop_current_ticks ( struct aws_event_loop *, uint64_t *ticks);

Gets the current tick count/timestamp for the event loop's clock. This function is thread-safe.

V-Table Shims

The remaining exported functions on event loop simply invoke the v-table functions and return. See the v-table section for more details.

Channels and Slots

Layout

struct aws_channel {
    struct aws_allocator *alloc;
    struct aws_event_loop *loop;
    struct aws_channel_slot *first;
};

struct aws_channel_slot {
    struct aws_allocator *alloc;
    struct aws_channel *channel;
    struct aws_channel_slot *adj_left;
    struct aws_channel_slot *adj_right;
    struct aws_channel_handler *handler;
};

API (Channel/Slot interaction)

struct aws_channel_slot_ref *aws_channel_slot_new (struct aws_channel *channel);

Creates a new slot using the channel's allocator, if it is the first slot in the channel, it will be added as the first slot in the channel. Otherwise, you'll need to use the insert or replace APIs for slots.

int aws_channel_slot_set_handler ( struct aws_channel_slot *, struct aws_channel_handler *handler );

Sets the handler on the slot. This should only be called once per slot.

int aws_channel_slot_remove (struct aws_channel_slot *slot);

Removes a slot from its channel. The slot and its handler will be cleaned up and deallocated.

int aws_channel_slot_replace (struct aws_channel_slot *remove, struct aws_channel_slot *new);

Replaces remove in the channel with new and cleans up and deallocates remove and its handler.

int aws_channel_slot_insert_right (struct aws_channel_slot *slot, struct aws_channel_slot_ref *right);

Adds a slot to the right of slot.

int aws_channel_slot_insert_left (struct aws_channel_slot *slot, struct aws_channel_slot_ref *left);

Adds a slot to the left of slot.

int aws_channel_slot_send_message (struct aws_channel_slot *slot, struct aws_io_message *message, enum aws_channel_direction dir);

Usually called by a handler, this calls the adjacent slot in the channel based on the dir argument. You may want to return any unneeded messages to the channel pool to avoid unnecessary allocations.

int aws_channel_slot_increment_read_window (struct aws_channel_slot *slot, size_t window);

Usually called by a handler, this function calls the left-adjacent slot.

int aws_channel_slot_on_handler_shutdown_complete(struct aws_channel_slot *slot, enum aws_channel_direction dir,
                                                              int err_code, bool abort_immediately);

Usually called by a handler, this function calls the adjacent slot's shutdown based on the dir argument.

API (Channel specific)

int aws_channel_init (struct aws_channel *channel, struct aws_allocator *alloc, struct aws_event_loop *el);

Initializes a channel for operation. The event loop will be used for driving the channel.

int aws_channel_clean_up (struct aws_channel *channel);

Cleans up resources for the channel.

int aws_channel_shutdown (struct aws_channel *channel,
    void (*on_shutdown_completed)(struct aws_channel *channel, void *user_data), void *user_data);

Starts the shutdown process, invokes on_shutdown_completed once each handler has shutdown.

int aws_channel_current_clock_time( struct aws_channel *, uint64_t *ticks);

Gets the current ticks from the event loop's clock.

int aws_channel_fetch_local_object ( struct aws_channel *, void *key, void **item);

Fetches data from the event loop's data store. This data is shared by each channel using that event loop.

int aws_channel_put_local_object ( struct aws_channel *, void *key, void *item);

Puts data into the event loop's data store. This data is shared by each channel using that event loop.

int aws_channel_schedule_task (struct aws_channel *, struct aws_task *task, uint64_t run_at);

Schedules a task to run on the event loop. This function is thread-safe.

BOOL aws_channel_thread_is_callers_thread (struct aws_channel *);

Checks if the caller is on the event loop's thread. This function is thread-safe.

Channel Handlers

Channel Handlers are runtime polymorphic. Here's some details on the virtual table (v-table):

Layout

struct aws_channel_handler {
    struct aws_channel_handler_vtable *vtable;
    struct aws_allocator *alloc;
    void *impl;
};

V-Table

struct aws_channel_handler_vtable {
    int (*data_in) ( struct aws_channel_handler *handler, struct aws_channel_slot *slot,
        struct aws_io_message *message );
    int (*data_out) ( struct aws_channel_handler *handler, struct aws_channel_slot *slot,
                struct aws_io_message *message );
    int (*on_window_update) (struct aws_channel_handler *handler, struct aws_channel_slot *slot, size_t size)
    int (*on_shutdown_notify) (struct aws_channel_handler *handler, struct aws_channel_slot *slot,
        enum aws_channel_direction dir, int error_code);
    int (*shutdown_direction) (struct aws_channel_handler *handler, struct aws_channel_slot *slot,
                enum aws_channel_direction dir);
    size_t (*initial_window_size) (struct aws_channel_handler *handler);
    void (*destroy)(struct aws_channel_handler *handler);
};

int data_in ( struct aws_channel_handler *handler, struct aws_channel_slot *slot, struct aws_io_message *message)

Data in is invoked by the slot when an application level message is received in the read direction (from the io). The job of the implementer is to process the data in msg and either notify a user or queue a new message on the slot's read queue.

int data_out (struct aws_channel_handler *handler, struct aws_channel_slot *slot, struct aws_io_message *message)

Data Out is invoked by the slot when an application level message is received in the write direction (to the io). The job of the implementer is to process the data in msg and either notify a user or queue a new message on the slot's write queue.

int increment_window (struct aws_channel_handler *handler, struct aws_channel_slot *slot, size_t size)

Increment Window is invoked by the slot when a framework level message is received from a downstream handler. It only applies in the read direction. This gives the handler a chance to make a programmatic decision about what its read window should be. Upon receiving an update_window message, a handler decides what its window should be and likely issues an increment window message to its slot. Shrinking a window has no effect. If a handler makes its window larger than a downstream window, it is responsible for honoring the downstream window and buffering any data it produces that is greater than that window.

int (*shutdown) (struct aws_channel_handler *handler, struct aws_channel_slot *slot, enum aws_channel_direction dir, int error_code, bool abort_immediately);

Shutdown is invoked by the slot when a framework level message is received from an adjacent handler. This notifies the handler that the previous handler in the chain has shutdown and will no longer be sending or receiving messages. The handler should make a decision about what it wants to do in response, and likely begins its shutdown process (if any). Once the handler has safely reached a safe state, if should call 'aws_channel_slot_on_handler_shutdown_complete'

size_t initial_window_size (struct aws_channel_handler *handler)

When a handler is added to a slot, the slot will call this function to determine the initial window size and will propagate a window_update message down the channel.

void destroy(struct aws_channel_handler *handler)

Clean up any memory or resources owned by this handler, and then deallocate the handler itself.

API

All exported functions, simply shim into the v-table and return.

Sockets

We include a cross-platform API for sockets. We support TCP and UDP using IPv4 and IPv6, and Unix Domain sockets. On Windows, we use Named Pipes to support the functionality of Unix Domain sockets. On Windows, this is implemented with winsock2, and on all unix platforms we use the posix API.

Upon a connection being established, the new socket (either as the result of a connect() or start_accept() call) will not be attached to any event loops. It is your responsibility to register it with an event loop to begin receiving notifications.

API

typedef enum aws_socket_domain {
    AWS_SOCKET_IPV4,
    AWS_SOCKET_IPV6,
    AWS_SOCKET_LOCAL,
    AWS_SOCKET_VSOCK,
} aws_socket_domain;

AWS_SOCKET_IPV4 means an IPv4 address will be used.

AWS_SOCKET_IPV6 means an IPv6 address will be used.

AWS_SOCKET_LOCAL means a socket path will be used for either a Unix Domain Socket or a Named Pipe on Windows.

typedef enum aws_socket_type {
    AWS_SOCKET_STREAM,
    AWS_SOCKET_DGRAM
} aws_socket_type;

AWS_SOCKET_VSOCK means a CID address will be used. Note: VSOCK is currently only available on Linux with an appropriate VSOCK kernel driver installed. -DUSE_VSOCK needs to be passed during compilation to enable VSOCK support.

AWS_SOCKET_STREAM is TCP or a connection oriented socket.

AWS_SOCKET_DGRAM is UDP

struct aws_socket_creation_args {
    void(*on_incoming_connection)(struct aws_socket *socket, struct aws_socket *new_socket, void *user_data);
    void(*on_connection_established)(struct aws_socket *socket, void *user_data);
    void(*on_error)(struct aws_socket *socket, int err_code, void *user_data);
    void *user_data;
};

on_incoming_connection() will be invoked on a listening socket when new connections arrive. socket is the listening socket. new_socket is the newly created socket. It is the connection to the remote endpoint.

NOTE: You are responsible for calling aws_socket_clean_up() and aws_mem_release() on new_socket when you are finished with it.

on_connection_established() will be invoked after a connect call, upon a successful connection to the remote endpoint.

on_error() will be invoked on both listening and connecting sockets to indicate any error conditions.

struct aws_socket_endpoint {
    char address[48];
    char socket_name[108];
    char port[10];
};

address can be either an IPv4, IPv6 or VSOCK CID address. This can be used for UDP or TCP. socket_name is only used in LOCAL mode. port can be used for TCP or UDP.

int aws_socket_init(struct aws_socket *socket, struct aws_allocator *alloc,
                                    struct aws_socket_options *options,
                                    struct aws_event_loop *connection_loop,
                                    struct aws_socket_creation_args *creation_args);

Initializes a socket object with socket options, an event loop to use for non-blocking operations, and callbacks to invoke upon completion of asynchronous operations. If you are using UDP or LOCAL, connection_loop may be NULL.

void aws_socket_clean_up(struct aws_socket *socket);

Shuts down any pending operations on the socket, and cleans up state. The socket object can be re initialized after this operation.

int aws_socket_connect(struct aws_socket *socket, struct aws_socket_endpoint *remote_endpoint);

Connects to a remote endpoint. In UDP, this simply binds the socket to a remote address for use with aws_socket_write(), and if the operation is successful, the socket can immediately be used for write operations.

In TCP, this will function will not block. If the return value is successful, then you must wait on the on_connection_established() callback to be invoked before using the socket.

For LOCAL (Unix Domain Sockets or Named Pipes), the socket will be immediately ready for use upon a successful return.

int aws_socket_bind(struct aws_socket *socket, struct aws_socket_endpoint *local_endpoint);

Binds the socket to a local address. In UDP mode, the socket is ready for aws_socket_read() operations. In connection oriented modes, you still must call aws_socket_listen() and aws_socket_start_accept() before using the socket.

int aws_socket_listen(struct aws_socket *socket, int backlog_size);

TCP and LOCAL only. Sets up the socket to listen on the address bound to in aws_socket_bind().

int aws_socket_start_accept(struct aws_socket *socket);

TCP and LOCAL only. The socket will begin accepting new connections. This is an asynchronous operation. New connections will arrive via the on_incoming_connection() callback.

int aws_socket_stop_accept(struct aws_socket *socket);

TCP and LOCAL only. The socket will shutdown the listener. It is safe to call aws_socket_start_accept() again after this operation.

int aws_socket_close(struct aws_socket *socket);

Calls close() on the socket and unregisters all io operations from the event loop.

struct aws_io_handle *aws_socket_get_io_handle(struct aws_socket *socket);

Fetches the underlying io handle for use in event loop registrations and channel handlers.

int aws_socket_set_options(struct aws_socket *socket, struct aws_socket_options *options);

Sets new socket options on the underlying socket. This is mainly useful in context of accepting a new connection via: on_incoming_connection().

int aws_socket_read(struct aws_socket *socket, struct aws_byte_buf *buffer, size_t *amount_read);

Reads from the socket. This call is non-blocking and will return AWS_IO_SOCKET_READ_WOULD_BLOCK if no data is available. amount_read is the amount of data read into buffer.

int aws_socket_write(struct aws_socket *socket, const struct aws_byte_buf *buffer, size_t *written);

Writes to the socket. This call is non-blocking and will return AWS_IO_SOCKET_WRITE_WOULD_BLOCK if no data could be written. written is the amount of data read from buffer and successfully written to socket.

aws-c-io's People

Contributors

alexw91 avatar bretambrose avatar coldencullen avatar davidogunsaws avatar dmitriymusatkin avatar feliperodri avatar giordano avatar graebm avatar holyzsiraf avatar hyandell avatar jamiehunter avatar jmklix avatar jonathanhenson avatar justinboswell avatar kankri avatar knightjoel avatar massi-ang avatar matthewbauer avatar nchong-at-aws avatar quinnj avatar rccarper avatar sbstevek avatar sdavtaker avatar sergeyryabinin avatar tingdaok avatar twistedtwigleg avatar waahm7 avatar xhochy avatar xiazhvera avatar yasminetalby avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aws-c-io's Issues

Calling setenv during init is unsafe for multithreaded programs

We have an application that runs on Linux and uses the AWS C++ SDK. It's a multithreaded application, and for reasons it initializes the AWS SDK (and transitively the aws-c-io library) after there are already a number of threads executing. Some of these threads may at times call getenv. We get crashes in these getenv calls if they occur concurrently with aws-c-io init, which calls setenv in aws_tls_init_static_state. According to the glibc docs, "Modifications of environment variables are not allowed in multi-threaded programs."

It would be better to avoid the setenv call.

Intel VTune linker errors

Describe the bug

I am currently using a few AWS C++ libraries that use this library transitively via CMake FetchContent and a recent commit has introduced linker errors for Intel VTune symbols.

Intel VTune should be an optional dependency with a CMake option to enable it.

Expected Behavior

Library should compile and link successfully.

Current Behavior

Library fails with link errors if Intel VTune is not installed as a system dependency:

/bin/ld: ../../../_deps/aws-chime-sdk-build/crt/aws-crt-cpp/crt/aws-c-io/libaws-c-io.a(epoll_event_loop.c.o): in function `aws_event_loop_thread':
/home/djr/dev/project/build/_deps/aws-chime-sdk-src/crt/aws-crt-cpp/crt/aws-c-io/source/linux/epoll_event_loop.c:620: undefined reference to `__itt_task_begin_ptr__3_0'
/bin/ld: /home/djr/dev/project/build/_deps/aws-chime-sdk-src/crt/aws-crt-cpp/crt/aws-c-io/source/linux/epoll_event_loop.c:651: undefined reference to `__itt_task_begin_ptr__3_0'
/bin/ld: /home/djr/dev/project/build/_deps/aws-chime-sdk-src/crt/aws-crt-cpp/crt/aws-c-io/source/linux/epoll_event_loop.c:653: undefined reference to `__itt_task_end_ptr__3_0'
/bin/ld: /home/djr/dev/project/build/_deps/aws-chime-sdk-src/crt/aws-crt-cpp/crt/aws-c-io/source/linux/epoll_event_loop.c:656: undefined reference to `__itt_task_end_ptr__3_0'
/bin/ld: /home/djr/dev/project/build/_deps/aws-chime-sdk-src/crt/aws-crt-cpp/crt/aws-c-io/source/linux/epoll_event_loop.c:665: undefined reference to `__itt_task_begin_ptr__3_0'
/bin/ld: /home/djr/dev/project/build/_deps/aws-chime-sdk-src/crt/aws-crt-cpp/crt/aws-c-io/source/linux/epoll_event_loop.c:667: undefined reference to `__itt_task_end_ptr__3_0'
/bin/ld: ../../../_deps/aws-chime-sdk-build/crt/aws-crt-cpp/crt/aws-c-io/libaws-c-io.a(stream.c.o): in function `aws_input_stream_read':
/home/djr/dev/project/build/_deps/aws-chime-sdk-src/crt/aws-crt-cpp/crt/aws-c-io/source/stream.c:36: undefined reference to `__itt_task_begin_ptr__3_0'
/bin/ld: /home/djr/dev/project/build/_deps/aws-chime-sdk-src/crt/aws-crt-cpp/crt/aws-c-io/source/stream.c:38: undefined reference to `__itt_task_end_ptr__3_0'
/bin/ld: ../../../_deps/aws-chime-sdk-build/crt/aws-crt-cpp/crt/aws-c-io/libaws-c-io.a(tracing.c.o): in function `aws_io_tracing_init':
/home/djr/dev/project/build/_deps/aws-chime-sdk-src/crt/aws-crt-cpp/crt/aws-c-io/source/tracing.c:15: undefined reference to `__itt_domain_create_ptr__3_0'
/bin/ld: /home/djr/dev/project/build/_deps/aws-chime-sdk-src/crt/aws-crt-cpp/crt/aws-c-io/source/tracing.c:16: undefined reference to `__itt_string_handle_create_ptr__3_0'
collect2: error: ld returned 1 exit status

Reproduction Steps

Create a CMake project.
Add aws-c-io as a dependency using FetchContent
Build the project.

Possible Solution

The commit that introduced the issue should be reverted to allow the project to continue to build.
It can then be re-introduced with a CMake option to enable VTune

Additional Information/Context

No response

aws-c-io version used

v0.14.0

Compiler and version used

g++ (GCC) 13.2.1 20230801

Operating System and version

Arch Linux (6.6.6-arch1-1)

CPU pinning in event_loop.c

Hi,
In the follwoing code in event_loop.c, by doing AWS_ZERO_STRUCT on thread_options, thh core_id is set to 0. The aws_thread_launch then tries to pin the thread to core 0. Is this by design?. Should the default core_id be set to -1, as in default thread_options?

struct aws_thread_options thread_options;    
AWS_ZERO_STRUCT(thread_options);    
thread_options.join_strategy = AWS_TJS_MANAGED;
AWS_FATAL_ASSERT( aws_thread_launch(&amp;cleanup_thread, s_event_loop_destroy_async_thread_fn, el_group, &amp;thread_options) ==        AWS_OP_SUCCESS);

Fail of the AcquireCredentialsHandleA for TLS 1.3

Describe the bug

AcquireCredentialsHandleA return 0x80090331 for TLS1.3 protocol which leads to negotiation error AWS_IO_TLS_ERROR_NEGOTIATION_FAILURE. Same methods with same credentials works fine for lower TLS versions

Note: current issue was initially registered for AWS CPP SDK aws/aws-sdk-cpp#2709

Expected Behavior

AcquireCredentialsHandleA should return SEC_E_OK for any TLS protocol versions

Current Behavior

AcquireCredentialsHandleA fails for latest master on given moment

SECURITY_STATUS status = AcquireCredentialsHandleA(

Reproduction Steps

activate AWS_IO_TLSv1_3 version for tls handler

Possible Solution

According to MS learn
https://learn.microsoft.com/en-us/answers/questions/708734/tls-1-3-doesnt-work-on-windows-11-through-schannel

In order to use TLS 1.3 with schannel, you should use the SCH_CREDENTIALS structure instead of the SCHANNEL_CRED structure with AcquireCredentialsHandle().

SCH_CREDENTIALS - Win32 apps | Microsoft Learn

i.e current sc_ctx->credentials which is pointer to SCHANNEL_CRED structure

SECURITY_STATUS status = AcquireCredentialsHandleA(
    NULL,
    UNISP_NAME,
    credential_use,
    NULL,
    &sc_ctx->credentials,//<-- currently it is SCHANNEL_CRED
   ...);

should be replaced on SCH_CREDENTIALS

Additional Information/Context

image

aws-c-io version used

v0.13.31

Compiler and version used

MSVS 2022 Professional

Operating System and version

Windows 11 x64

Windows handle leak

We have noticed that our application which uses aws-crt-cpp is leaking Windows thread handles in aws-c-io.

The issue can easily be caught with Application Verifier using the following steps. It would be nice if you could integrate Application Verifier, available in Windows Software Development Kit, into your test sets.

I checked out tag v1.12.6 of aws-iot-device-sdk-cpp-v2 and made the following changes to convert raw_pub_sub into a DLL and add a runner for it:

diff --git a/samples/mqtt/raw_pub_sub/CMakeLists.txt b/samples/mqtt/raw_pub_sub/CMakeLists.txt
index e13dd0a..1d001d7 100644
--- a/samples/mqtt/raw_pub_sub/CMakeLists.txt
+++ b/samples/mqtt/raw_pub_sub/CMakeLists.txt
@@ -6,7 +6,7 @@ file(GLOB SRC_FILES
        "*.cpp"
 )
 
-add_executable(${PROJECT_NAME} ${SRC_FILES})
+add_library(${PROJECT_NAME} SHARED ${SRC_FILES})
 
 set_target_properties(${PROJECT_NAME} PROPERTIES
     CXX_STANDARD 14)
diff --git a/samples/mqtt/raw_pub_sub/main.cpp b/samples/mqtt/raw_pub_sub/main.cpp
index 0a39efa..2800dab 100644
--- a/samples/mqtt/raw_pub_sub/main.cpp
+++ b/samples/mqtt/raw_pub_sub/main.cpp
@@ -63,6 +63,7 @@ char *s_getCmdOption(char **begin, char **end, const String &option)
     return 0;
 }
 
+extern "C" __declspec(dllexport)
 int main(int argc, char *argv[])
 {
 
diff --git a/samples/mqtt/runner/CMakeLists.txt b/samples/mqtt/runner/CMakeLists.txt
new file mode 100644
index 0000000..00e2f6f
--- /dev/null
+++ b/samples/mqtt/runner/CMakeLists.txt
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.1)
+# note: cxx-17 requires cmake 3.8, cxx-20 requires cmake 3.12
+project(runner CXX)
+
+file(GLOB SRC_FILES
+       "*.cpp"
+)
+
+add_executable(${PROJECT_NAME} ${SRC_FILES})
+
+set_target_properties(${PROJECT_NAME} PROPERTIES
+    CXX_STANDARD 14)
+
+#set warnings
+if (MSVC)
+    target_compile_options(${PROJECT_NAME} PRIVATE /W4 /wd4068)
+else ()
+    target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wno-long-long -pedantic -Werror)
+endif ()
+
diff --git a/samples/mqtt/runner/main.cpp b/samples/mqtt/runner/main.cpp
new file mode 100644
index 0000000..53cd4b4
--- /dev/null
+++ b/samples/mqtt/runner/main.cpp
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <windows.h>
+typedef int (WINAPI *fn_main_t)(int argc, char *argv[]);
+
+int main(int argc, char *argv[])
+{
+    HMODULE dll = LoadLibraryW(L"raw-pub-sub.dll");
+    fn_main_t fn_main = (fn_main_t)GetProcAddress(dll, "main");
+    int ret = fn_main(argc, argv);
+    BOOL status = FreeLibrary(dll);
+    Sleep(60*1000);
+    return ret;
+}

I then built both the sample program as a DLL and the runner and copied the DLL to a directory the runner finds it from:

cmake -DCMAKE_PREFIX_PATH=%CD%\_sdk -A x64 -S aws-iot-device-sdk-cpp-v2\samples\mqtt\raw_pub_sub -B _build_raw
cmake --build _build_raw --config "Debug"
cmake -A x64 -S aws-iot-device-sdk-cpp-v2\samples\mqtt\runner -B _runner
cmake --build _runner --config "Debug"
copy _build_raw\Debug\raw-pub-sub.dll _runner\Debug

I then enabled handle leak detection using an elevated user (this is easier to explore with the GUI):

appverif -enable leak -for runner.exe

I then ran the program:

_runner\Debug\runner.exe --endpoint ENDPOINT --cert CERT --key KEY --ca_file CA_FILE --topic TOPIC --client_id CLIENT_ID
<type "exit" immediately when program starts>

This caused a minidump to be generated (depending on the host configuration, see e.g. Collecting User-Mode Dumps) and a log file in %USERPROFILE%\AppVerifierLogs\runner.exe.*.dat. I exported the binary log file as XML:

appverif -export log -for runner.exe -with to=runner.exe.xml

The log says:

<avrf:message>A HANDLE was leaked.</avrf:message>
<avrf:parameter1>1a0 - Value of the leaked handle. Run !htrace &lt;handle&gt; to get additional information about the handle if handle tracing is enabled.</avrf:parameter1>
<avrf:parameter2>2878b6a4f30 - Address to the allocation stack trace. Run dps &lt;address&gt; to view the allocation stack.</avrf:parameter2>
<avrf:parameter3>287921c0fd6 - Address of the owner dll name. Run du &lt;address&gt; to read the dll name.</avrf:parameter3>
<avrf:parameter4>7ffb42670000 - Base of the owner dll. Run .reload &lt;dll_name&gt; = &lt;address&gt; to reload the owner dll. Use &apos;lm&apos; to get more information about the loaded and unloaded modules.</avrf:parameter4>

Opening the minidump with Windbg (or cdb.exe) and running the suggested command shows:

0:000> dps 2878b6a4f30
00000287`8b6a4f30  00000000`00000000
00000287`8b6a4f38  00100000`00009801
00000287`8b6a4f40  00007ffb`4277d10c raw_pub_sub!aws_thread_launch+0x19c [aws-iot-device-sdk-cpp-v2\crt\aws-crt-cpp\crt\aws-c-common\source\windows\thread.c @ 205]
00000287`8b6a4f48  00007ffb`4273318c raw_pub_sub!create_and_init_host_entry+0x43c [aws-iot-device-sdk-cpp-v2\crt\aws-crt-cpp\crt\aws-c-io\source\host_resolver.c @ 1364]
00000287`8b6a4f50  00007ffb`42733464 raw_pub_sub!default_resolve_host+0x264 [aws-iot-device-sdk-cpp-v2\crt\aws-crt-cpp\crt\aws-c-io\source\host_resolver.c @ 1411]
00000287`8b6a4f58  00007ffb`4272ee7c raw_pub_sub!aws_host_resolver_resolve_host+0x8c [aws-iot-device-sdk-cpp-v2\crt\aws-crt-cpp\crt\aws-c-io\source\host_resolver.c @ 76]
00000287`8b6a4f60  00007ffb`42734c7b raw_pub_sub!aws_client_bootstrap_new_socket_channel+0x46b [aws-iot-device-sdk-cpp-v2\crt\aws-crt-cpp\crt\aws-c-io\source\channel_bootstrap.c @ 780]
00000287`8b6a4f68  00007ffb`426b59f3 raw_pub_sub!s_mqtt_client_connect+0x183 [aws-iot-device-sdk-cpp-v2\crt\aws-crt-cpp\crt\aws-c-mqtt\source\client.c @ 1579]
00000287`8b6a4f70  00007ffb`426b31e7 raw_pub_sub!aws_mqtt_client_connection_connect+0xb07 [aws-iot-device-sdk-cpp-v2\crt\aws-crt-cpp\crt\aws-c-mqtt\source\client.c @ 1529]
00000287`8b6a4f78  00007ffb`42697686 raw_pub_sub!Aws::Crt::Mqtt::MqttConnection::Connect+0x316 [aws-iot-device-sdk-cpp-v2\crt\aws-crt-cpp\source\mqtt\mqttclient.cpp @ 405]
00000287`8b6a4f80  00007ffb`426728e1 raw_pub_sub!main+0x1431 [aws-iot-device-sdk-cpp-v2\samples\mqtt\raw_pub_sub\main.cpp @ 350]
0:000> lsa raw_pub_sub!aws_thread_launch+0x19c
   201:     if (is_managed_thread) {
   202:         aws_thread_increment_unjoined_count();
   203:     }
   204: 
>  205:     thread->thread_handle =
   206:         CreateThread(0, stack_size, thread_wrapper_fn, (LPVOID)thread_wrapper, 0, &thread->thread_id);
   207: 
   208:     if (!thread->thread_handle) {
   209:         aws_thread_decrement_unjoined_count();
   210:         return aws_raise_error(AWS_ERROR_THREAD_INSUFFICIENT_RESOURCE)
0:000> lsc
Current: aws-iot-device-sdk-cpp-v2\crt\aws-crt-cpp\crt\aws-c-common\source\windows\thread.c(211)

Alternatively in an interactive setting it might be easier to run the program directly under debugger:

windbg -g _runner\Debug\runner.exe --endpoint ENDPOINT --cert CERT --key KEY --ca_file CA_FILE --topic TOPIC --client_id CLIENT_ID
<type "exit" immediately when program starts>

=======================================
VERIFIER STOP 0000000000000901: pid 0x7FE4: A HANDLE was leaked.

	00000000000002F8 : Value of the leaked handle. Run !htrace <handle> to get additional information about the handle if handle tracing is enabled.
	000002170E5A62E0 : Address to the allocation stack trace. Run dps <address> to view the allocation stack.
	00000217150F0FD6 : Address of the owner dll name. Run du <address> to read the dll name.
	00007FFB1C9B0000 : Base of the owner dll. Run .reload <dll_name> = <address> to reload the owner dll. Use 'lm' to get more information about the loaded and unloaded modules.

Looking at the caller, create_and_init_host_entry() in aws-c-io/source/host_resolver.c:1364, it seems it receives struct aws_thread which contains a thread handle from aws_thread_launch() but never calls aws_thread_clean_up() for it. It seems that struct is not needed for anything, thread_wrapper contains a copy of it with a unique thread handle which is used to synchronize thread exit. So it should be safe to clean up the struct right away.

Wrong usage of MSG_NOSIGNAL on Linux

Hello,
i am trying to debug your socket implementation as it looks that there can be issue. First small one i found looks usage of MSG_NOSIGNAL.
Everywhere on internet i see this recomandation:

Code for OS X:

setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, ...)

Code for Linux (2.2+):

send(..., MSG_NOSIGNAL)

Your usage:

define NO_SIGNAL MSG_NOSIGNAL
if (AWS_UNLIKELY(
            setsockopt(socket->io_handle.data.fd, SOL_SOCKET, NO_SIGNAL, &option_value, sizeof(option_value)))) {
        AWS_LOGF_WARN(
            AWS_LS_IO_SOCKET,
            "id=%p fd=%d: setsockopt() for NO_SIGNAL failed with errno %d. If you are having SIGPIPE signals thrown, "
            "you may"
            " want to install a signal trap in your application layer.",
            (void *)socket,
            socket->io_handle.data.fd,
            errno);
    }

This looks like it should always return warning on Linux systems...
Here is descrition for send and MSG_NOSIGNAL definition: https://linux.die.net/man/2/send
Here setsockopt definition with missing MSG_NOSIGNAL definition: https://linux.die.net/man/3/setsockopt

Linking error with ClientBootstrap

Confirm by changing [ ] to [x] below:

Platform/OS/Device
What are you running the sdk on?
Cross compiler - Ubuntu 17.04
GCC version - gcc (Ubuntu 6.3.0-12ubuntu2) 6.3.0 20170406
CMAKE_CXX_STANDARD - 14

Describe the question
I am facing a linking issue such as below when I am integrating aws-iot-device-sdk into my application. I am using cross-compiler to compile, but the build is failing on the arm device too. Surprisingly I am facing no issues running the standalone basic_pub_sub application. But integrating it to main application is causing the issue.

/home/armcrossc/devbroot/usr/share/libiotsdk_release/lib/libaws-crt-cpp.a(Bootstrap.cpp.o): In function `Aws::Crt::Io::ClientBootstrap::~ClientBootstrap()':
Bootstrap.cpp:(.text+0x1a4): undefined reference to `__cxa_init_primary_exception'
Bootstrap.cpp:(.text+0x1c8): undefined reference to `std::__exception_ptr::exception_ptr::exception_ptr(void*)'
/home/armcrossc/devbroot/usr/share/libiotsdk_release/lib/libaws-crt-cpp.a(Bootstrap.cpp.o): In function `Aws::Crt::Io::ClientBootstrapCallbackData::OnShutdownComplete(void*)':
Bootstrap.cpp:(.text._ZN3Aws3Crt2Io27ClientBootstrapCallbackData18OnShutdownCompleteEPv[_ZN3Aws3Crt2Io27ClientBootstrapCallbackData18OnShutdownCompleteEPv]+0x254): undefined reference to `__cxa_init_primary_exception'
Bootstrap.cpp:(.text._ZN3Aws3Crt2Io27ClientBootstrapCallbackData18OnShutdownCompleteEPv[_ZN3Aws3Crt2Io27ClientBootstrapCallbackData18OnShutdownCompleteEPv]+0x278): undefined reference to `std::__exception_ptr::exception_ptr::exception_ptr(void*)'
collect2: error: ld returned 1 exit status

the toolchain file looks like this

SET(CMAKE_SYSTEM_NAME Linux)

SET(TARGET_ABI "linux-gnu")
set(CMAKE_SYSROOT /home/armcrossc/devbroot)

# specify the cross compiler
SET(CMAKE_C_COMPILER   aarch64-${TARGET_ABI}-gcc-6)
SET(CMAKE_CXX_COMPILER aarch64-${TARGET_ABI}-g++-6)
set(CMAKE_LIBRARY_ARCHITECTURE aarch64-linux-gnu)

set(CMAKE_C_FLAGS "-I${CMAKE_SYSROOT}/usr/include/${CMAKE_LIBRARY_ARCHITECTURE}" CACHE STRING "" FORCE)
set(CMAKE_C_LINK_FLAGS "-Wl,-rpath-link=${CMAKE_SYSROOT}/lib/${CMAKE_LIBRARY_ARCHITECTURE} -Wl,-rpath-link=${CMAKE_SYSROOT}/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}" CACHE STRING "" FORCE)


# To build the tests, we need to set where the target environment containing
# the required library is. On Debian-like systems, this is
# /usr/aarch64-linux-gnu.
SET(CMAKE_FIND_ROOT_PATH /home/armcrossc/devbroot)
# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)```

But I am facing the same issue while building on the device, so the toolchain might not be the issue.
Can the GCC version cause the above errors?
Please let me know what could be the issue.

PS: I opened the issue here also because the linking error is caused by this package I believe. (Original issue)

ThreadSanitizer reports in host_resolver

  1. In source/host_resolver.c the last_use variable is shared between threads so should be atomic to be data-race free. The variable is 64-bit so cannot be trivially turned into a aws_atomic_var, which is 32-bits on 32-bit platforms. Currently, we exclude resolver tests when running Thread Sanitizer regressions.

Failing tests when instrumented: test_resolver_ttls, test_resolver_connect_failure_recording, test_resolver_ttl_refreshes_on_resolve

Building with crt-builder fails on OpenBSD

Hi. With the merging of #545 and awslabs/aws-crt-builder#217, I've been working on adding a CI job for OpenBSD to aws-c-io. When I build aws-c-io using the cmake commands in README.md, everything builds and tests just fine. When I use crt-builder, it fails to link:

% aws-crt-builder/build/builder build -p aws-c-io
[...]
[100%] Linking C executable aws-c-io-tests
ld: error: undefined symbol: CRYPTO_get_id_callback
>>> referenced by openssl_platform_init.c:565 (/home/joel/aws-c-io/build/deps/aws-c-cal/source/unix/openssl_platform_init.c:565)
>>>               openssl_platform_init.c.o:(aws_cal_platform_init) in archive /home/joel/aws-c-io/build/install/lib/libaws-c-cal.a
>>> referenced by openssl_platform_init.c:582 (/home/joel/aws-c-io/build/deps/aws-c-cal/source/unix/openssl_platform_init.c:582)
>>>               openssl_platform_init.c.o:(aws_cal_platform_clean_up) in archive /home/joel/aws-c-io/build/install/lib/libaws-c-cal.a
>>> did you mean: CRYPTO_set_id_callback
>>> defined in: /home/joel/aws-c-io/build/install/lib/libcrypto.a(thread.c.o)
clang: error: linker command failed with exit code 1 (use -v to see invocation)
*** Error 1 in . (tests/CMakeFiles/aws-c-io-tests.dir/build.make:439 'tests/aws-c-io-tests')
*** Error 2 in . (CMakeFiles/Makefile2:882 'tests/CMakeFiles/aws-c-io-tests.dir/all')
*** Error 2 in /home/joel/aws-c-io/build/aws-c-io (Makefile:146 'all': /usr/bin/make -s -f CMakeFiles/Makefile2 all)
Failed to run cmake --build /home/joel/aws-c-io/build/aws-c-io --config RelWithDebInfo --target install: Command exited with code 2

Note the error is bubbling up from aws-c-cal, however I can run builder build -p aws-c-cal directly and it builds and tests just fine on its own.

Looking at aws-c-io/build/deps/aws-c-cal/source/unix/openssl_platform_init.c, it looks like OPENSSL_IS_AWSLC is not being defined when building via crt-builder. I'm running in circles trying to debug what conditions cause that define to be set and why things are different under crt-builder vs running cmake directly. I'm looking for insight or pointers that will unblock me. Thanks for reading.

test fails: ld: error: lib/libaws-c-cal.so.1.0.0: undefined reference to aws_device_random_buffer_append [--no-allow-shlib-undefined]

Describe the bug

Build with BUILD_TESTING fails.

Expected Behavior

Test pass

Current Behavior

[100% 50/50] cd /wrkdirs/usr/ports/devel/aws-c-io/work/.build/tests && /usr/local/bin/cmake -E copy_directory /wrkdirs/usr/ports/devel/aws-c-io/work/aws-c-io-0.13.21/tests/resources /wrkdirs/usr/ports/devel/aws-c-io/work/.build/tests && cd /wrkdirs/usr/ports/devel/aws-c-io/work/.build && /usr/bin/cc -O2 -pipe  -fstack-protector-strong -fno-strict-aliasing -O2 -pipe  -fstack-protector-strong -fno-strict-aliasing  -DNDEBUG -fstack-protector-strong     -Wl,--exclude-libs,libcrypto.a tests/CMakeFiles/aws-c-io-tests.dir/test_runner.c.o tests/CMakeFiles/aws-c-io-tests.dir/alpn_handler_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/byo_crypto_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/channel_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/default_host_resolver_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/event_loop_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/exponential_backoff_retry_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/io_lib_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/io_testing_channel_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/mock_dns_resolver.c.o tests/CMakeFiles/aws-c-io-tests.dir/pem_utils_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/pipe_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/pkcs11_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/pki_utils_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/read_write_test_handler.c.o tests/CMakeFiles/aws-c-io-tests.dir/shared_library_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/socket_handler_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/socket_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/standard_retry_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/statistics_handler_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/stream_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/tls_handler_test.c.o -o tests/aws-c-io-tests  -Wl,-rpath,/wrkdirs/usr/ports/devel/aws-c-io/work/.build:/usr/local/lib  libaws-c-io.so.1.0.0  /usr/local/lib/libs2n.so.1.0.0  /usr/local/lib/libaws-c-cal.so.1.0.0  /usr/local/lib/libaws-c-common.so.1.0.0  -ldl  -lthr  -lexecinfo  -lm  /usr/lib/libcrypto.so && :
FAILED: tests/aws-c-io-tests
cd /wrkdirs/usr/ports/devel/aws-c-io/work/.build/tests && /usr/local/bin/cmake -E copy_directory /wrkdirs/usr/ports/devel/aws-c-io/work/aws-c-io-0.13.21/tests/resources /wrkdirs/usr/ports/devel/aws-c-io/work/.build/tests && cd /wrkdirs/usr/ports/devel/aws-c-io/work/.build && /usr/bin/cc -O2 -pipe  -fstack-protector-strong -fno-strict-aliasing -O2 -pipe  -fstack-protector-strong -fno-strict-aliasing  -DNDEBUG -fstack-protector-strong     -Wl,--exclude-libs,libcrypto.a tests/CMakeFiles/aws-c-io-tests.dir/test_runner.c.o tests/CMakeFiles/aws-c-io-tests.dir/alpn_handler_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/byo_crypto_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/channel_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/default_host_resolver_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/event_loop_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/exponential_backoff_retry_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/io_lib_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/io_testing_channel_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/mock_dns_resolver.c.o tests/CMakeFiles/aws-c-io-tests.dir/pem_utils_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/pipe_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/pkcs11_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/pki_utils_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/read_write_test_handler.c.o tests/CMakeFiles/aws-c-io-tests.dir/shared_library_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/socket_handler_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/socket_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/standard_retry_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/statistics_handler_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/stream_test.c.o tests/CMakeFiles/aws-c-io-tests.dir/tls_handler_test.c.o -o tests/aws-c-io-tests  -Wl,-rpath,/wrkdirs/usr/ports/devel/aws-c-io/work/.build:/usr/local/lib  libaws-c-io.so.1.0.0  /usr/local/lib/libs2n.so.1.0.0  /usr/local/lib/libaws-c-cal.so.1.0.0  /usr/local/lib/libaws-c-common.so.1.0.0  -ldl  -lthr  -lexecinfo  -lm  /usr/lib/libcrypto.so && :
ld: error: /usr/local/lib/libaws-c-cal.so.1.0.0: undefined reference to aws_device_random_buffer_append [--no-allow-shlib-undefined]
cc: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
===> Compilation failed unexpectedly.

Reproduction Steps

Use BUILD_TESTING

Possible Solution

No response

Additional Information/Context

No response

aws-c-io version used

0.13.21

Compiler and version used

clang 14.0.5

Operating System and version

FreeBSD 13.2 amd64

ECC Support

When attempting to connect to a HTTPS website using ECC certificates I get the following error (e.g. using elasticurl):

./elasticurl https://ecc256.badssl.com
Connection failed with error aws-c-io: AWS_IO_TLS_ERROR_NEGOTIATION_FAILURE, TLS (SSL) negotiation failed

Does the aws_tls_ctx_options parameter expose support for ECC keys? Alternatively is it possible to add a test case for ECC support, similar to the other baddssl.com tests?

Thanks

Questions about "Release" and "Pre-release" tags

hello,

I'm looking to package awscliv2 source build for Funtoo Linux, and this is in the dependency chain for that.
Funtoo has a system that can automatically bump package versions in sync with upstream. The only thing is this package (aws-c-io) has all the tarballs tagged as prerelease.

So I guess the question is: what are the criteria before y'all tag a tarball as "Release" ?

Thank you,
seemant

Support custom keychain on macOS

In aws/aws-iot-device-sdk-cpp-v2#163 I suggested adding support for using a custom keychain instead of the default login keychain for use-cases like daemons using the AWS IoT SDK. It was suggested that I'd instead change the default keychain for the account to the private keychain, or just a PKCS#12 file which appeared to not use a keychain.

As commented in the ticket, now when doing the daemon integration, we wound that changing the default keychain of the daemon account appeared to cause some other issues, and using PKCS#12 appears to also rely on the default keychain. To avoid dealing with the default keychain, I'd wish to add support for optionally using a custom private keychain for the IoT TLS connections only.

There's also a related issue awslabs/aws-crt-cpp#204 which implements the changes needed to the C++ wrapper to support these changes.

Investigate data-races reported by TSan

Thread Sanitizer / TSan (https://clang.llvm.org/docs/ThreadSanitizer.html) uses compile-time instrumentation to detect data-races at runtime. The analysis is precise so reported bugs should be looked into.

The following works for me on my Mac:

git clone [email protected]:awslabs/aws-c-io.git
cd aws-c-io/
./build-deps.sh -DCMAKE_C_FLAGS="-g" -DENABLE_SANITIZERS=ON -DSANITIZERS=",thread"
cd build
cmake -GNinja -DCMAKE_C_FLAGS="-g" -DENABLE_SANITIZERS=ON -DSANITIZERS=",thread" -DCMAKE_INSTALL_PREFIX=`pwd`/deps/install -DCMAKE_PREFIX_PATH=`pwd`/deps/install/ ..
ninja install
ninja test

With the following failures:

[...snip...]
The following tests FAILED:
	 43 - connect_timeout (Child aborted)
	 44 - connect_timeout_cancelation (Child aborted)
	 50 - cleanup_before_connect_or_timeout_doesnt_explode (Child aborted)
	 56 - channel_refcount_delays_clean_up (Child aborted)
	 61 - channel_connect_some_hosts_timeout (Child aborted)
	 62 - channel_message_passing (Child aborted)
	 63 - test_default_with_ipv6_lookup (Child aborted)
	 64 - test_resolver_ipv6_address_lookup (Child aborted)
	 65 - test_default_with_multiple_lookups (Child aborted)
	 66 - test_resolver_ipv4_address_lookup (Child aborted)
	 67 - test_default_with_ipv4_only_lookup (Child aborted)
	 68 - test_resolver_ttls (Child aborted)
	 69 - test_resolver_connect_failure_recording (Child aborted)
	 70 - test_resolver_ttl_refreshes_on_resolve (Child aborted)
	 80 - socket_handler_echo_and_backpressure (Child aborted)
	 81 - socket_handler_close (Timeout)
	 83 - tls_client_channel_negotiation_error_expired (Child aborted)
	 84 - tls_client_channel_negotiation_error_wrong_host (Child aborted)
	 85 - tls_client_channel_negotiation_error_self_signed (Child aborted)
	 86 - tls_client_channel_negotiation_error_untrusted_root (Child aborted)
	 87 - tls_client_channel_negotiation_error_socket_closed (Child aborted)
	 88 - tls_client_channel_negotiation_success (Child aborted)
	 91 - tls_client_channel_no_verify (Child aborted)

For example, two races are due to the use of volatile non-atomics in host_resolver.c: last_use and keep_active, which can be concurrently accessed by different threads. These should be replaced with atomic equivalents.

Host cannot be resolved when port is specified

Don't know if this is the correct repo to put this issue on, found it when I used the S3 CRT client. If an endpoint override is set with host:port will gettaddrinfo() not be able to resolve the host since the string isn't splitted and service argument isn't used in the host resolver.

int err_code = getaddrinfo(hostname_cstr, NULL, &hints, &result);

aws_tls_handler_write exists in header file, but there's no implementation?

Describe the bug

The tls_channel_handler.h file includes the following declaration:

/**
 * Not necessary if you are installing more handlers into the channel, but if you just want to have TLS for arbitrary
 * data and use the channel handler directly, this function allows you to write data to the channel and have it
 * encrypted.
 */
AWS_IO_API int aws_tls_handler_write(
    struct aws_channel_handler *handler,
    struct aws_channel_slot *slot,
    struct aws_byte_buf *buf,
    aws_channel_on_message_write_completed_fn *on_write_completed,
    void *completion_user_data);

But there doesn't seem to be a generic or any platform-specific implementations of the function.

Expected Behavior

Have an implementation of this function.

Current Behavior

Can't use the function

Reproduction Steps

Tried to use function but discovered I couldn't

Possible Solution

No response

Additional Information/Context

No response

aws-c-io version used

latest master

Compiler and version used

not exactly sure; can find out if needed

Operating System and version

pretty up-to-date macos

Connect failed, create socket failed.

Hi,
i am trying to connect to aws iot cloud using aws-iot-device-sdk-python-v2. Everytime i am starting app, or when reconnecting i am getting these errors finished by Connected message and application is working well. But i am curios why these errors happening? Looks like they are related to this repository. Demo code example: aws/aws-iot-device-sdk-python-v2#90

[ERROR] [2020-07-25T12:30:01Z] [00007f5d7b0ac700] [socket] - id=0x7f5d6c004e90 fd=6: connect failed with error code 101.
[INFO ] [2020-07-25T12:30:01Z] [00007f5d7b0ac700] [dns] - id=0x1004a40: recording failure for record 2600:1f00:6000::385:ab7e for a1tuyp21t3nvof-ats.iot.us-east-2.amazonaws.com, moving to bad list
[ERROR] [2020-07-25T12:30:01Z] [00007f5d7b0ac700] [channel-bootstrap] - id=0x1032890: failed to create socket with error 1049
[INFO ] [2020-07-25T12:30:01Z] [00007f5d7b0ac700] [socket] - id=0x7f5d6c004e90 fd=6: connection success
[aws] Connected!

How to build?

I tried to build this project using the instructions from aws-c-common but got the following errors. Is there documentation on how to build this project locally?

$ git clone https://github.com/awslabs/aws-c-io.git
...
$ mkdir aws-c-io-build
$ cd aws-c-io-build/
$ cmake ../aws-c-io
-- The C compiler identification is GNU 7.5.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
CMake Error at CMakeLists.txt:30 (include):
  include could not find load file:

    AwsCFlags


CMake Error at CMakeLists.txt:31 (include):
  include could not find load file:

    AwsCheckHeaders


CMake Error at CMakeLists.txt:32 (include):
  include could not find load file:

    AwsSharedLibSetup


CMake Error at CMakeLists.txt:33 (include):
  include could not find load file:

    AwsSanitizers


CMake Error at CMakeLists.txt:34 (include):
  include could not find load file:

    AwsFindPackage


CMake Error at CMakeLists.txt:159 (aws_use_package):
  Unknown CMake command "aws_use_package".
...

Warning messages if endpoint url is invalid

Hello,

I am working under Mac OS X and with python 3.7.1 in a conda environment. Using invalid endpoint argument (iot.us-east-1.amazonaws.com) results in strange error messages.

  • First case: I suggest checking the endpoint argument for the correct format first (abcd123456wxyz-ats.iot.us-east-1.amazonaws.com).
  • Second case: Also, I suggest throwing a warning if people do not use the ats endpoint (abcd123456wxyz.iot.eu-central-1.amazonaws.com).

The first case produces the following output currently. It seems like message->allocator is not set:

''' Connecting to iot.eu-central-1.amazonaws.com with client ID 'DemoDevice'...
Fatal error condition occurred in /Users/Shared/Jenkins/Home/workspace/aws-crt-python-build-wheels-osx/aws-crt-python/aws-common-runtime/aws-c-common/source/allocator.c:176: allocator != ((void*)0)
Exiting Application
'''
...
'''
################################################################################
Raw stacktrace:
################################################################################
1 _awscrt.cpython-37m-darwin.so 0x000000010281e5e3 s_print_stack_trace + 19
2 libsystem_platform.dylib 0x00007fff685ca5fd _sigtramp + 29
3 ??? 0x0000000000000000 0x0 + 0
4 libsystem_c.dylib 0x00007fff684a0808 abort + 120
5 _awscrt.cpython-37m-darwin.so 0x00000001028221db aws_fatal_assert + 75
6 _awscrt.cpython-37m-darwin.so 0x0000000102821074 aws_mem_release + 52
7 _awscrt.cpython-37m-darwin.so 0x0000000102840910 s_do_read + 336
8 _awscrt.cpython-37m-darwin.so 0x00000001028402dc s_on_readable_notification + 92
9 _awscrt.cpython-37m-darwin.so 0x000000010283edde s_on_socket_io_event + 350
10 _awscrt.cpython-37m-darwin.so 0x000000010282eecc s_event_thread_main + 956
11 _awscrt.cpython-37m-darwin.so 0x000000010282bf28 thread_fn + 88
12 libsystem_pthread.dylib 0x00007fff685d6109 _pthread_start + 148
13 libsystem_pthread.dylib 0x00007fff685d1b8b thread_start + 15
'''

The second case produces:

'''
Connecting to akkh9376u0e33.iot.eu-central-1.amazonaws.com with client ID 'DemoDevice'...
Traceback (most recent call last):
File "src/backgroundworker/sample.py", line 132, in
connect_future.result()
File "/Users/tobiasjacob/anaconda3/lib/python3.7/concurrent/futures/_base.py", line 432, in result
return self.__get_result()
File "/Users/tobiasjacob/anaconda3/lib/python3.7/concurrent/futures/_base.py", line 384, in __get_result
raise self._exception
awscrt.exceptions.AwsCrtError: AwsCrtError(name='AWS_IO_TLS_ERROR_NEGOTIATION_FAILURE', message='TLS (SSL) negotiation failed', code=1029)
'''

Rework connection establishment timeout

As we add support for more complex connection setups (proxies with auth subnegotiations are a good example), we should reconsider our notion of timeout. Currently we have a socket level timeout for the initial TCP handshake, but then nothing further. We don't want a million separate timeouts for each step of connection establishment, so we may want to just have a single, generic, "establishment timeout" that governs the time period between bootstrap initiation and when the user's success/failure callback is invoked.

aws-c-io includes Windows.h in public headers

The Windows.h header has started being included in aws-c-io public headers, notably aws/io/event_loop.h. This in turns gets exposed into aws-sdk-cpp public headers, and can have repercussions on downstream users (especially due to Windows' habit of defining many macros with common names).

Why did you remove libuv?

Hiya!

I'm just wondering why you removed libuv, no judging, I just ended up in this repo in my quest to integrate the aws cpp s3 sdk into my event loop utilizing server.

Thanks for your time!

Incorrect format string in default_resolve_host

aws trying to log
host_name->bytes
in
AWS_LOGF_DEBUG(AWS_LS_IO_DNS, "id=%p: Host resolution requested for %s", (void *)resolver, host_name->bytes);
the matching format string parameter is "%s", however host_name->bytes is of type:
const uint8_t bytes[1];
which is generally not null terminated.

Default trust store not found

I'm trying to use AWS CRT client, however initialization is failing with

Caused by: s.amazon.awssdk.crt.CrtRuntimeException: TlsContext.tls_ctx_new: Failed to create new aws_tls_ctx (aws_last_error: AWS_IO_TLS_ERROR_DEFAULT_TRUST_STORE_NOT_FOUND(1173), Default TLS trust store not found on this system. Trusted CA certificates must be installed, or "override default trust store" must be used while creating the TLS context.)
	at software.amazon.awssdk.crt.io.TlsContext.tlsContextNew(TlsContext.java)
	at software.amazon.awssdk.crt.io.TlsContext.<init>(TlsContext.java:24)
	at s.a.a.http.crt.AwsCrtAsyncHttpClient.<init>(AwsCrtAsyncHttpClient.java:104)
	at s.a.a.http.crt.AwsCrtAsyncHttpClient.<init>(AwsCrtAsyncHttpClient.java:73)
	at s.a.a.h.c.AwsCrtAsyncHttpClient$DefaultBuilder.buildWithDefaults(AwsCrtAsyncHttpClient.java:405)

Default cacert is available at JAVA_HOME/jre/lib/security/cacerts..... is there something else we need to configure.

This is the sample code

return AwsCrtAsyncHttpClient.builder().build()

Related discussion: aws/aws-sdk-java-v2#3898

tls_double_channel test gets stuck

I am building and running tests for aws-c-io 0.10.9 at Arch Linux in a clean chroot environment. The project itself builds fine but the tests are stuck:

        Start  97: socket_handler_close
 97/173 Test  #97: socket_handler_close .....................................................   Passed    0.02 sec
        Start  98: test_concurrent_cert_import
 98/173 Test  #98: test_concurrent_cert_import ..............................................   Passed    0.00 sec
        Start  99: tls_channel_echo_and_backpressure_test
 99/173 Test  #99: tls_channel_echo_and_backpressure_test ...................................   Passed    0.03 sec
        Start 100: tls_client_channel_negotiation_error_expired
100/173 Test #100: tls_client_channel_negotiation_error_expired .............................   Passed   13.12 sec
        Start 101: tls_client_channel_negotiation_error_wrong_host
101/173 Test #101: tls_client_channel_negotiation_error_wrong_host ..........................   Passed   26.13 sec
        Start 102: tls_client_channel_negotiation_error_wrong_host_with_ca_override
102/173 Test #102: tls_client_channel_negotiation_error_wrong_host_with_ca_override .........   Passed   24.06 sec
        Start 103: tls_client_channel_negotiation_error_self_signed
103/173 Test #103: tls_client_channel_negotiation_error_self_signed .........................   Passed   29.13 sec
        Start 104: tls_client_channel_negotiation_error_untrusted_root
104/173 Test #104: tls_client_channel_negotiation_error_untrusted_root ......................   Passed   30.14 sec
        Start 105: tls_client_channel_negotiation_error_untrusted_root_due_to_ca_override
105/173 Test #105: tls_client_channel_negotiation_error_untrusted_root_due_to_ca_override ...   Passed   23.16 sec
        Start 106: tls_client_channel_negotiation_no_verify_expired
106/173 Test #106: tls_client_channel_negotiation_no_verify_expired .........................   Passed    1.03 sec
        Start 107: tls_client_channel_negotiation_no_verify_wrong_host
107/173 Test #107: tls_client_channel_negotiation_no_verify_wrong_host ......................   Passed    1.03 sec
        Start 108: tls_client_channel_negotiation_no_verify_self_signed
108/173 Test #108: tls_client_channel_negotiation_no_verify_self_signed .....................   Passed    1.02 sec
        Start 109: tls_client_channel_negotiation_no_verify_untrusted_root
109/173 Test #109: tls_client_channel_negotiation_no_verify_untrusted_root ..................   Passed    1.03 sec
        Start 110: tls_client_channel_negotiation_error_socket_closed
110/173 Test #110: tls_client_channel_negotiation_error_socket_closed .......................   Passed   23.21 sec
        Start 111: tls_client_channel_negotiation_success
111/173 Test #111: tls_client_channel_negotiation_success ...................................   Passed    1.05 sec
        Start 112: tls_client_channel_negotiation_success_ecc256
112/173 Test #112: tls_client_channel_negotiation_success_ecc256 ............................   Passed    1.10 sec
        Start 113: tls_client_channel_negotiation_success_ecc384
113/173 Test #113: tls_client_channel_negotiation_success_ecc384 ............................   Passed    1.10 sec
        Start 114: tls_server_multiple_connections
114/173 Test #114: tls_server_multiple_connections ..........................................   Passed    0.03 sec
        Start 115: tls_server_hangup_during_negotiation
115/173 Test #115: tls_server_hangup_during_negotiation .....................................   Passed    1.03 sec
        Start 116: tls_client_channel_no_verify
116/173 Test #116: tls_client_channel_no_verify .............................................   Passed    1.04 sec
        Start 117: test_tls_negotiation_timeout
117/173 Test #117: test_tls_negotiation_timeout .............................................   Passed    1.03 sec
        Start 118: tls_double_channel

Is there a way to understand what is going on with the tests?

error open urandom

I am using AWS SDK to develop an ODBC driver. Our code is running on github. The test works fine locally on Ubuntu 20.04. It also could run successfully until Aug 9. But from yesterday the test on github starts to fail like below. It is from Aws::InitAPI(). As it is AWS SDK code we have no idea what is wrong. Just from the error info it seems /dev/urandom could not be accessed.

One more thing we noticed is the aws-c-io which calls s2n is updated from 0.10.7 to 0.10.22. Not sure if this causes the problem. Please help to have a check. Thanks!

--error info
2022-08-12T01:51:39.3781517Z s2n_init() failed: 402653198 (error opening urandom)
2022-08-12T01:51:39.3782986Z Fatal error condition occurred in /home/runner/work/amazon-timestream-odbc-driver/amazon-timestream-odbc-driver/vcpkg/buildtrees/aws-c-io/src/f2a46b436e-18f356d7b4.clean/source/s2n/s2n_tls_channel_handler.c:187: 0 && "s2n_init() failed"

--call stack
2022-08-12T01:51:39.3864476Z /home/runner/work/amazon-timestream-odbc-driver/amazon-timestream-odbc-driver/src/../build/odbc/lib/libtimestream-odbc.so.2.13.0.58917(aws_backtrace_print+0xba) [0x7f0212002fb8]
2022-08-12T01:51:39.3865476Z /home/runner/work/amazon-timestream-odbc-driver/amazon-timestream-odbc-driver/src/../build/odbc/lib/libtimestream-odbc.so.2.13.0.58917(aws_fatal_assert+0x5f) [0x7f0211feea7e]
2022-08-12T01:51:39.3866464Z /home/runner/work/amazon-timestream-odbc-driver/amazon-timestream-odbc-driver/src/../build/odbc/lib/libtimestream-odbc.so.2.13.0.58917(aws_tls_init_static_state+0x115) [0x7f0211e4d981]
2022-08-12T01:51:39.3867438Z /home/runner/work/amazon-timestream-odbc-driver/amazon-timestream-odbc-driver/src/../build/odbc/lib/libtimestream-odbc.so.2.13.0.58917(aws_io_library_init+0x61) [0x7f0211e40f1a]
2022-08-12T01:51:39.3868405Z /home/runner/work/amazon-timestream-odbc-driver/amazon-timestream-odbc-driver/src/../build/odbc/lib/libtimestream-odbc.so.2.13.0.58917(aws_mqtt_library_init+0x31) [0x7f0211dc91e3]
2022-08-12T01:51:39.3869332Z /home/runner/work/amazon-timestream-odbc-driver/amazon-timestream-odbc-driver/src/../build/odbc/lib/libtimestream-odbc.so.2.13.0.58917(+0xdbce06) [0x7f0211dabe06]
2022-08-12T01:51:39.3870707Z /home/runner/work/amazon-timestream-odbc-driver/amazon-timestream-odbc-driver/src/../build/odbc/lib/libtimestream-odbc.so.2.13.0.58917(_ZN3Aws3Crt9ApiHandleC1EP13aws_allocator+0x4e) [0x7f0211dabea6]
2022-08-12T01:51:39.3871805Z /home/runner/work/amazon-timestream-odbc-driver/amazon-timestream-odbc-driver/src/../build/odbc/lib/libtimestream-odbc.so.2.13.0.58917(ZN3Aws3NewINS_3Crt9ApiHandleEJP13aws_allocatorEEEPT_PKcDpOT0+0x5a) [0x7f021198d787]
2022-08-12T01:51:39.3872982Z /home/runner/work/amazon-timestream-odbc-driver/amazon-timestream-odbc-driver/src/../build/odbc/lib/libtimestream-odbc.so.2.13.0.58917(_ZN3Aws13InitializeCrtEv+0x37) [0x7f021198d3df]
2022-08-12T01:51:39.3873996Z /home/runner/work/amazon-timestream-odbc-driver/amazon-timestream-odbc-driver/src/../build/odbc/lib/libtimestream-odbc.so.2.13.0.58917(_ZN3Aws7InitAPIERKNS_10SDKOptionsE+0x2b) [0x7f0211989470]

SECURITY_STATUS is 590615 - S3 download hang after partial parts have completed

This behave only happened under Windows.
When downloading large S3 object with S3AsyncClient in java
Application will hang when only partial parts have completed.

[DEBUG] [2023-03-11T15:02:50Z] [000005e0] [S3MetaRequest] - id=000001CB43412B40: 11 out of 24 parts have completed.

trace log report a shutdown connection because of SECURITY_STATUS is 590615, which I believe leads to remain parts get no chance to start again.

[TRACE] [2023-03-11T15:02:54Z] [000009ec] [dns] - static: remaining record count for host 0
[TRACE] [2023-03-11T15:02:54Z] [000009ec] [dns] - static: remaining record count for host 7
[DEBUG] [2023-03-11T15:02:55Z] [000009ec] [dns] - static: resolving host mt-test1.s3.cn-north-1.amazonaws.com.cn
[DEBUG] [2023-03-11T15:02:55Z] [000009ec] [dns] - static: resolved record: 54.222.51.15
[DEBUG] [2023-03-11T15:02:55Z] [000009ec] [dns] - static, resolving host mt-test1.s3.cn-north-1.amazonaws.com.cn successful, returned 1 addresses
[DEBUG] [2023-03-11T15:02:55Z] [000009ec] [dns] - static: new address resolved 54.222.51.15 for host mt-test1.s3.cn-north-1.amazonaws.com.cn caching
[TRACE] [2023-03-11T15:02:55Z] [000009ec] [dns] - static: remaining record count for host 0
[TRACE] [2023-03-11T15:02:55Z] [000009ec] [dns] - static: remaining record count for host 8
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [event-loop] - id=000001CB42EA3F40: wake up with 1 events to process.
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [event-loop] - id=000001CB42EA3F40: invoking handler.
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [socket] - id=000001CB4320DFC0 handle=0000000000000928: socket readable event triggered
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [socket-handler] - id=000001CB42EB1D20: socket is now readable
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [socket-handler] - id=000001CB42EB1D20: invoking read. Downstream window 18446744073709551615, max_to_read 262144
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [channel] - id=000001CB42F7EF40: acquired message 000001CB41A3E1C0 of capacity 262144 from pool 000001CB4329D180. Requested size was 262144
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [socket] - id=000001CB4320DFC0 handle=0000000000000928: reading from socket
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [socket] - id=000001CB4320DFC0 handle=0000000000000928: read 31 bytes from socket
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [socket-handler] - id=000001CB42EB1D20: read 31 from socket
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [channel] - id=000001CB42F7EF40: sending read message of size 31, from slot 000001CB4437E050 to slot 000001CB4437F4F0 with handler 000001CB443D0E80.
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [tls-handler] - id=000001CB443D0E80: processing incoming message of size 31
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [tls-handler] - id=000001CB443D0E80: Alert received. Message sender has shut down the connection. SECURITY_STATUS is 590615.
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [channel] - id=000001CB42F7EF40: channel shutdown task is scheduled
[TRACE] [2023-03-11T15:02:55Z] [000018e8] [channel] - id=000001CB42F7EF40: scheduling task with wrapper task id 000001CB42F7F120.

Is this a expected behave on Windows ?

Add support for larger ECC curves (P521) in the PKCS11 implementation

Describe the feature

In attempting to use P521 with PKCS (SoftHSM), I encounter the AWS_ERROR_PKCS11_ENCODING_ERROR here:

return aws_raise_error(AWS_ERROR_PKCS11_ENCODING_ERROR);
. It seems to be the case that the buffer is too small for P521. P256 and P384 are fine.

Use Case

AWS IoT Core recently added ECDSA-P521 as a supported key type: https://aws.amazon.com/about-aws/whats-new/2023/07/aws-iot-core-new-certificate-signing-key-generation-algorithms/. The SDK should support all key algorithms supported by IoT Core.

Proposed Solution

No response

Other Information

No response

Acknowledgements

  • I may be able to implement this feature request
  • This feature might incur a breaking change

Support for truncated (as opposed to unbounded) exponential backoff

Describe the feature

The original AWS post that introduced exponential backoff for request retries used truncated exponential back-off.

The aws-c-io supports variations of jitter:

static compute_backoff_fn *s_backoff_compute_table[] = {
    [AWS_EXPONENTIAL_BACKOFF_JITTER_DEFAULT] = s_compute_full_jitter,
    [AWS_EXPONENTIAL_BACKOFF_JITTER_NONE] = s_compute_no_jitter,
    [AWS_EXPONENTIAL_BACKOFF_JITTER_FULL] = s_compute_full_jitter,
    [AWS_EXPONENTIAL_BACKOFF_JITTER_DECORRELATED] = s_compute_deccorelated_jitter,
};

However, none of the variants support truncated exponential back-off.

Use Case

Truncated back-off allows the user to set a cap/maximum value of the retry interval, to suit network/load conditions, or to configure for a maximum total retry time.

This is especially important when costs are proportional to application runtime, such as services running on a kubernetes pod.

For this reason, we have had the requirement to use truncated back-off.

Proposed Solution

Update AWS_EXPONENTIAL_BACKOFF_JITTER_FULL (the default) to support truncated backoff via configuration.

A maximum upper bound of 0 can disable the feature and be set as default value, to retain backward compatibility.

Other Information

No response

Acknowledgements

  • I may be able to implement this feature request
  • This feature might incur a breaking change

retry strategy logs not emitting?

Describe the bug

I'm building a higher-level HTTP client using aws-c-http, and in the normal course of development, I sometimes enable aws logging down to the debug/trace level to try and identify problems. This works well by calling aws_logger_set_log_level, but curiously, the retry strategy logs don't seem to be emitted. Take this sample of logs for example:

[DEBUG] [2023-09-08T22:37:14Z] [00000002028ca080] [channel-bootstrap] - id=0x600000a4c7e0: acquiring bootstrap reference
[TRACE] [2023-09-08T22:37:14Z] [00000002028ca080] [event-loop] - id=0x600000256850: scheduling task 0x600003490440 cross-thread for timestamp 2447234044077916
[TRACE] [2023-09-08T22:37:14Z] [00000002028ca080] [event-loop] - id=0x600000256850: signaling event-loop that cross-thread tasks need to be scheduled.
[INFO] [2023-09-08T22:37:14Z] [00000002028ca080] [connection-manager] - id=0x124f25930: Successfully created
[TRACE] [2023-09-08T22:37:14Z] [00000002a36b7000] [event-loop] - id=0x600000256850: wake up with 1 events to process.
[TRACE] [2023-09-08T22:37:14Z] [00000002a36b7000] [event-loop] - id=0x600000256850: notified of cross-thread data to process
[TRACE] [2023-09-08T22:37:14Z] [00000002a36b7000] [event-loop] - id=0x600000256850: processing cross-thread tasks
[TRACE] [2023-09-08T22:37:14Z] [00000002a36b7000] [event-loop] - id=0x600000256850: task 0x600003490440 pulled to event-loop, scheduling now.
[DEBUG] [2023-09-08T22:37:14Z] [00000002a36b7000] [task-scheduler] - id=0x600003490440: Scheduling cull_idle_connections task for future execution at time 2447234044077916
[TRACE] [2023-09-08T22:37:14Z] [00000002a36b7000] [event-loop] - id=0x600000256850: running scheduled tasks.
[TRACE] [2023-09-08T22:37:14Z] [00000002a36b7000] [event-loop] - id=0x600000256850: detected more scheduled tasks with the next occurring at 13095482167 using timeout of 13s 95482167ns.
[TRACE] [2023-09-08T22:37:14Z] [00000002a36b7000] [event-loop] - id=0x600000256850: waiting for a maximum of 13s 95482167ns
[ Info: acquiring retry token: 127.0.0.1
[TRACE] [2023-09-08T22:37:14Z] [00000002028ca080] [event-loop] - id=0x600000256940: scheduling task 0x2b1d3d7b0 cross-thread for timestamp 0
[TRACE] [2023-09-08T22:37:14Z] [00000002028ca080] [event-loop] - id=0x600000256940: signaling event-loop that cross-thread tasks need to be scheduled.
[TRACE] [2023-09-08T22:37:14Z] [00000002a362b000] [event-loop] - id=0x600000256940: wake up with 1 events to process.
[TRACE] [2023-09-08T22:37:14Z] [00000002a362b000] [event-loop] - id=0x600000256940: notified of cross-thread data to process
[TRACE] [2023-09-08T22:37:14Z] [00000002a362b000] [event-loop] - id=0x600000256940: processing cross-thread tasks
[TRACE] [2023-09-08T22:37:14Z] [00000002a362b000] [event-loop] - id=0x600000256940: task 0x2b1d3d7b0 pulled to event-loop, scheduling now.
[DEBUG] [2023-09-08T22:37:14Z] [00000002a362b000] [task-scheduler] - id=0x2b1d3d7b0: Scheduling aws_exponential_backoff_retry_task task for immediate execution
[TRACE] [2023-09-08T22:37:14Z] [00000002a362b000] [event-loop] - id=0x600000256940: running scheduled tasks.
[DEBUG] [2023-09-08T22:37:14Z] [00000002a362b000] [task-scheduler] - id=0x2b1d3d7b0: Running aws_exponential_backoff_retry_task task with <Running> status
[ Info: acquired retry token, acquiring connection: 127.0.0.1
[DEBUG] [2023-09-08T22:37:14Z] [00000002a362b000] [connection-manager] - id=0x124f25930: Acquire connection
[DEBUG] [2023-09-08T22:37:14Z] [00000002a362b000] [connection-manager] - id=0x124f25930: snapshot - state=1, idle_connection_count=0, pending_acquire_count=1, pending_settings_count=0, pending_connect_count=1, vended_connection_count=0, open_connection_count=0, ref_count=1

this is from an initial http request where I'm creating a new connection manager and retry strategy, but only the connection-manager logs are coming through. We can even see that backoff_retry_task is getting scheduled once the retry strategy is initialized, (ref: Scheduling aws_exponential_backoff_retry_task task for immediate execution), but we're missing, for example, the following log when first creating the retry strategy:

AWS_LOGF_INFO(AWS_LS_IO_STANDARD_RETRY_STRATEGY, "static: creating new standard retry strategy");

And indeed, I don't see any retry strategy related logs throughout my log tracing.

I tried to snoop around the various "log subject" related functionality, but as far as I can tell, the default pipeline logger doesn't actually allow or do any filtering on log subjects, so I'm at a loss as to why these logs specifically aren't coming through, while other aws-c-io logs seem to be just fine (e.g. event-loop, etc.).

Do I have something misconfigured somehow?

Expected Behavior

Expecting the retry-strategy related logs to be emitted like other aws-c-io component logs.

Current Behavior

No retry strategy logs are being emitted when log level is set to maximum (i.e. trace).

Reproduction Steps

I have pretty standard debug shared library builds locally, and I'm loading them from Julia (programming language) then using the Julia FFI to call various exported aws-c-* library functions, including setting/initializing a global logger, setting the global logger to output to stderr, etc. This all seems to be working as expected except the retry strategy logs.

Possible Solution

No response

Additional Information/Context

No response

aws-c-io version used

248e39a

Compiler and version used

not exactly sure; can find out if needed

Operating System and version

pretty up-to-date macos

Treating all warnings as errors breaks build on mipsel-openwrt crosscompiler

Treating all warnings as errors breaks build on mipsel-openwrt crosscompiler env:

mipsel-openwrt-linux-gcc: warning: environment variable 'STAGING_DIR' not defined
[ 65%] Building C object CMakeFiles/aws-c-io.dir/source/posix/socket.c.o
mipsel-openwrt-linux-gcc: warning: environment variable 'STAGING_DIR' not defined
In file included from /opt/aws-crt-python/aws-common-runtime/aws-c-io/source/posix/socket.c:30:0:
/mysource/staging_dir/toolchain-mipsel_24kc_gcc-7.3.0_musl/include/sys/errno.h:1:2: error: #warning redirecting incorrect #include <sys/errno.h> to <errno.h> [-Werror=cpp]
 #warning redirecting incorrect #include <sys/errno.h> to <errno.h>
  ^~~~~~~
cc1: all warnings being treated as errors
make[2]: *** [CMakeFiles/aws-c-io.dir/build.make:262: CMakeFiles/aws-c-io.dir/source/posix/socket.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:93: CMakeFiles/aws-c-io.dir/all] Error 2
make: *** [Makefile:147: all] Error 2

PKCS11 support

Storing the private key in a file is not a good approach in terms of security.
A solution is adding an HW crypto device with PKCS11 support.

Could you please accomplish a direct read of the key via PKCS11

VSOCK socket client would almost always fail

Describe the bug

Function s_update_local_endpoint(struct aws_socket *socket) defined at
source/posix/socket.c#L273 has the following logic:

        /* VSOCK port is 32bit, but aws_socket_endpoint.port is only 16bit.
         * Hopefully this isn't an issue, since users can only pass in 16bit values.
         * But if it becomes an issue, we'll need to make aws_socket_endpoint more flexible */
        if (s->svm_port > UINT16_MAX) {
            AWS_LOGF_ERROR(
                AWS_LS_IO_SOCKET,
                "id=%p fd=%d: aws_socket_endpoint can't deal with VSOCK port > UINT16_MAX",
                (void *)socket,
                socket->io_handle.data.fd);
            return aws_raise_error(AWS_IO_SOCKET_INVALID_ADDRESS);
        }
        tmp_endpoint.port = (uint16_t)s->svm_port;

When it is used as a client, it would almost always fail, as the ephemeral port grabbed from the system is likely be large number. How did we test this code?

Expected Behavior

aws_socket_connect() should succeed

Current Behavior

Failure with aws_socket_endpoint can't deal with VSOCK port > UINT16_MAX

Reproduction Steps

Create a client and connect to any VSOCK address

Possible Solution

use 32 bit port number

Additional Information/Context

No response

aws-c-io version used

version containing df07e42

Compiler and version used

clang14

Operating System and version

Linux

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.