Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/aws/http/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ enum aws_http_errors {
AWS_ERROR_HTTP_OUTGOING_STREAM_LENGTH_INCORRECT,
AWS_ERROR_HTTP_CALLBACK_FAILURE,
AWS_ERROR_HTTP_WEBSOCKET_CLOSE_FRAME_SENT,
AWS_ERROR_HTTP_WEBSOCKET_IS_MIDCHANNEL_HANDLER,
AWS_ERROR_HTTP_END_RANGE = 0x0C00,
};

Expand Down
8 changes: 3 additions & 5 deletions include/aws/http/private/websocket_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ struct aws_websocket_frame {

struct aws_websocket_handler_options {
struct aws_allocator *allocator;
struct aws_channel_slot *channel_slot;
struct aws_channel *channel;
size_t initial_window_size;

void *user_data;
Expand All @@ -88,12 +88,10 @@ AWS_HTTP_API
uint64_t aws_websocket_frame_encoded_size(const struct aws_websocket_frame *frame);

/**
* Returns channel-handler for websocket.
* handler->impl is the aws_websocket*
* To destroy a handler that was never put into a channel, invoke: `handler->vtable.destroy(handler)`
* Create a websocket channel-handler and insert it into the channel.
*/
AWS_HTTP_API
struct aws_channel_handler *aws_websocket_handler_new(const struct aws_websocket_handler_options *options);
struct aws_websocket *aws_websocket_handler_new(const struct aws_websocket_handler_options *options);

AWS_EXTERN_C_END
#endif /* AWS_HTTP_WEBSOCKET_IMPL_H */
50 changes: 28 additions & 22 deletions include/aws/http/websocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@

#include <aws/http/http.h>

struct aws_channel_handler;
struct aws_http_header;

/* TODO: Document lifetime stuff */
/* TODO: Should shutdown callback fire when it's a midchannel handler? */
/* TODO: Document CLOSE frame behavior (when auto-sent during close, when auto-closed) */
/* TODO: Document auto-pong behavior */

Expand Down Expand Up @@ -236,25 +234,15 @@ bool aws_websocket_is_data_frame(uint8_t opcode);
AWS_HTTP_API
int aws_websocket_client_connect(const struct aws_websocket_client_connection_options *options);

/* TODO: Require all users to manually grab a hold? Http doesn't work like that... */
/* TODO: should the last release trigger a shutdown automatically? http does that, channel doesn't. */

/**
* Ensure that the websocket cannot be destroyed until aws_websocket_release_hold() is called.
* The websocket might still shutdown/close, but the public API will not crash when this websocket pointer is used.
* If acquire_hold() is never called, the websocket is destroyed when its channel its channel is destroyed.
* This function may be called from any thread.
*/
AWS_HTTP_API
void aws_websocket_acquire_hold(struct aws_websocket *websocket);

/**
* See aws_websocket_acquire_hold().
* The websocket will shut itself down when the last hold is released.
* Users must release the websocket when they are done with it (unless it's been converted to a mid-channel handler).
* The websocket's memory cannot be reclaimed until this is done.
* If the websocket connection was not already shutting down, it will be shut down.
* Callbacks may continue firing after this is called, with "shutdown" being the final callback.
* This function may be called from any thread.
*/
AWS_HTTP_API
void aws_websocket_release_hold(struct aws_websocket *websocket);
void aws_websocket_release(struct aws_websocket *websocket);

/**
* Close the websocket connection.
Expand Down Expand Up @@ -285,11 +273,29 @@ int aws_websocket_send_frame(struct aws_websocket *websocket, const struct aws_w
AWS_HTTP_API
void aws_websocket_increment_read_window(struct aws_websocket *websocket, size_t size);

/* WIP */
/**
* Convert the websocket into a mid-channel handler.
* The websocket will stop being usable via its public API and become just another handler in the channel.
* The caller will likely install a channel handler to the right.
* This must not be called in the middle of an incoming frame (between "frame begin" and "frame complete" callbacks).
* This MUST be called from the websocket's thread.
*
* If successful, the channel that the websocket belongs to is returned and:
* - The websocket will ignore all further calls to aws_websocket_X() functions.
* - The websocket will no longer invoke any "incoming frame" callbacks.
* - There is no need to invoke aws_websocket_release(), the websocket will be destroyed when the channel is destroyed.
* The caller should acquire a hold on the channel if they need to prevent its destruction.
* - aws_io_messages written by a downstream handler will be wrapped in binary data frames and sent upstream.
* The data may be split/combined as it is sent along.
* - aws_io_messages read from upstream handlers will be scanned for binary data frames.
* The payloads of these frames will be sent downstream.
* The payloads may be split/combined as they are sent along.
* - An incoming close frame will automatically result in channel-shutdown.
*
* If unsuccessful, NULL is returned and the websocket is unchanged.
*/
AWS_HTTP_API
int aws_websocket_install_channel_handler_to_right(
struct aws_websocket *websocket,
struct aws_channel_handler *right_handler);
struct aws_channel *aws_websocket_convert_to_midchannel_handler(struct aws_websocket *websocket);

AWS_EXTERN_C_END

Expand Down
3 changes: 3 additions & 0 deletions source/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ static struct aws_error_info s_errors[] = {
AWS_DEFINE_ERROR_INFO_HTTP(
AWS_ERROR_HTTP_WEBSOCKET_CLOSE_FRAME_SENT,
"Websocket has sent CLOSE frame, no more data will be sent."),
AWS_DEFINE_ERROR_INFO_HTTP(
AWS_ERROR_HTTP_WEBSOCKET_IS_MIDCHANNEL_HANDLER,
"Operation cannot be performed because websocket has been converted to a midchannel handler."),
AWS_DEFINE_ERROR_INFO_HTTP(
AWS_ERROR_HTTP_END_RANGE,
"Not a real error and should never be seen."),
Expand Down
Loading