Skip to content

Commit

Permalink
aws_websocket_convert_to_midchannel_handler() (#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
graebm authored May 20, 2019
1 parent 1fdf2e6 commit b787708
Show file tree
Hide file tree
Showing 7 changed files with 439 additions and 118 deletions.
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

0 comments on commit b787708

Please sign in to comment.