Skip to content

Commit b787708

Browse files
authored
aws_websocket_convert_to_midchannel_handler() (#52)
1 parent 1fdf2e6 commit b787708

File tree

7 files changed

+439
-118
lines changed

7 files changed

+439
-118
lines changed

include/aws/http/http.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ enum aws_http_errors {
3030
AWS_ERROR_HTTP_OUTGOING_STREAM_LENGTH_INCORRECT,
3131
AWS_ERROR_HTTP_CALLBACK_FAILURE,
3232
AWS_ERROR_HTTP_WEBSOCKET_CLOSE_FRAME_SENT,
33+
AWS_ERROR_HTTP_WEBSOCKET_IS_MIDCHANNEL_HANDLER,
3334
AWS_ERROR_HTTP_END_RANGE = 0x0C00,
3435
};
3536

include/aws/http/private/websocket_impl.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ struct aws_websocket_frame {
6161

6262
struct aws_websocket_handler_options {
6363
struct aws_allocator *allocator;
64-
struct aws_channel_slot *channel_slot;
64+
struct aws_channel *channel;
6565
size_t initial_window_size;
6666

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

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

9896
AWS_EXTERN_C_END
9997
#endif /* AWS_HTTP_WEBSOCKET_IMPL_H */

include/aws/http/websocket.h

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@
1717

1818
#include <aws/http/http.h>
1919

20-
struct aws_channel_handler;
21-
struct aws_http_header;
22-
2320
/* TODO: Document lifetime stuff */
21+
/* TODO: Should shutdown callback fire when it's a midchannel handler? */
2422
/* TODO: Document CLOSE frame behavior (when auto-sent during close, when auto-closed) */
2523
/* TODO: Document auto-pong behavior */
2624

@@ -236,25 +234,15 @@ bool aws_websocket_is_data_frame(uint8_t opcode);
236234
AWS_HTTP_API
237235
int aws_websocket_client_connect(const struct aws_websocket_client_connection_options *options);
238236

239-
/* TODO: Require all users to manually grab a hold? Http doesn't work like that... */
240-
/* TODO: should the last release trigger a shutdown automatically? http does that, channel doesn't. */
241-
242-
/**
243-
* Ensure that the websocket cannot be destroyed until aws_websocket_release_hold() is called.
244-
* The websocket might still shutdown/close, but the public API will not crash when this websocket pointer is used.
245-
* If acquire_hold() is never called, the websocket is destroyed when its channel its channel is destroyed.
246-
* This function may be called from any thread.
247-
*/
248-
AWS_HTTP_API
249-
void aws_websocket_acquire_hold(struct aws_websocket *websocket);
250-
251237
/**
252-
* See aws_websocket_acquire_hold().
253-
* The websocket will shut itself down when the last hold is released.
238+
* Users must release the websocket when they are done with it (unless it's been converted to a mid-channel handler).
239+
* The websocket's memory cannot be reclaimed until this is done.
240+
* If the websocket connection was not already shutting down, it will be shut down.
241+
* Callbacks may continue firing after this is called, with "shutdown" being the final callback.
254242
* This function may be called from any thread.
255243
*/
256244
AWS_HTTP_API
257-
void aws_websocket_release_hold(struct aws_websocket *websocket);
245+
void aws_websocket_release(struct aws_websocket *websocket);
258246

259247
/**
260248
* Close the websocket connection.
@@ -285,11 +273,29 @@ int aws_websocket_send_frame(struct aws_websocket *websocket, const struct aws_w
285273
AWS_HTTP_API
286274
void aws_websocket_increment_read_window(struct aws_websocket *websocket, size_t size);
287275

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

294300
AWS_EXTERN_C_END
295301

source/http.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ static struct aws_error_info s_errors[] = {
5858
AWS_DEFINE_ERROR_INFO_HTTP(
5959
AWS_ERROR_HTTP_WEBSOCKET_CLOSE_FRAME_SENT,
6060
"Websocket has sent CLOSE frame, no more data will be sent."),
61+
AWS_DEFINE_ERROR_INFO_HTTP(
62+
AWS_ERROR_HTTP_WEBSOCKET_IS_MIDCHANNEL_HANDLER,
63+
"Operation cannot be performed because websocket has been converted to a midchannel handler."),
6164
AWS_DEFINE_ERROR_INFO_HTTP(
6265
AWS_ERROR_HTTP_END_RANGE,
6366
"Not a real error and should never be seen."),

0 commit comments

Comments
 (0)