diff options
Diffstat (limited to 'libsoup/soup-websocket-connection.c')
-rw-r--r-- | libsoup/soup-websocket-connection.c | 94 |
1 files changed, 81 insertions, 13 deletions
diff --git a/libsoup/soup-websocket-connection.c b/libsoup/soup-websocket-connection.c index ed82a27c..8f58961e 100644 --- a/libsoup/soup-websocket-connection.c +++ b/libsoup/soup-websocket-connection.c @@ -535,6 +535,59 @@ too_big_error_and_close (SoupWebsocketConnection *self, } static void +close_connection (SoupWebsocketConnection *self, + gushort code, + const char *data) +{ + SoupWebsocketQueueFlags flags; + SoupWebsocketConnectionPrivate *pv; + + pv = self->pv; + + if (pv->close_sent) { + g_debug ("close code already sent"); + return; + } + + /* Validate the closing code received by the peer */ + switch (code) { + case SOUP_WEBSOCKET_CLOSE_NORMAL: + case SOUP_WEBSOCKET_CLOSE_GOING_AWAY: + case SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR: + case SOUP_WEBSOCKET_CLOSE_UNSUPPORTED_DATA: + case SOUP_WEBSOCKET_CLOSE_BAD_DATA: + case SOUP_WEBSOCKET_CLOSE_POLICY_VIOLATION: + case SOUP_WEBSOCKET_CLOSE_TOO_BIG: + break; + case SOUP_WEBSOCKET_CLOSE_NO_EXTENSION: + if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER) { + g_debug ("Wrong closing code %d received for a server connection", + code); + break; + } + case SOUP_WEBSOCKET_CLOSE_SERVER_ERROR: + if (pv->connection_type != SOUP_WEBSOCKET_CONNECTION_SERVER) { + g_debug ("Wrong closing code %d received for a non server connection", + code); + break; + } + default: + g_debug ("Wrong closing code %d received", code); + } + + g_signal_emit (self, signals[CLOSING], 0); + + if (pv->close_received) + g_debug ("responding to close request"); + + flags = 0; + if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER && pv->close_received) + flags |= SOUP_WEBSOCKET_QUEUE_LAST; + send_close (self, flags, code, data); + close_io_after_timeout (self); +} + +static void receive_close (SoupWebsocketConnection *self, const guint8 *data, gsize len) @@ -565,8 +618,33 @@ receive_close (SoupWebsocketConnection *self, if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER) close_io_stream (self); } else { - /* Send back the response */ - soup_websocket_connection_close (self, pv->peer_close_code, NULL); + /* Validate the closing code received by the peer */ + switch (pv->peer_close_code) { + case SOUP_WEBSOCKET_CLOSE_NO_EXTENSION: + if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER) { + g_debug ("Wrong closing code %d received for a server connection", + pv->peer_close_code); + break; + } + case SOUP_WEBSOCKET_CLOSE_SERVER_ERROR: + if (pv->connection_type != SOUP_WEBSOCKET_CONNECTION_SERVER) { + g_debug ("Wrong closing code %d received for a non server connection", + pv->peer_close_code); + break; + } + case SOUP_WEBSOCKET_CLOSE_NORMAL: + case SOUP_WEBSOCKET_CLOSE_GOING_AWAY: + case SOUP_WEBSOCKET_CLOSE_PROTOCOL_ERROR: + case SOUP_WEBSOCKET_CLOSE_UNSUPPORTED_DATA: + case SOUP_WEBSOCKET_CLOSE_BAD_DATA: + case SOUP_WEBSOCKET_CLOSE_POLICY_VIOLATION: + case SOUP_WEBSOCKET_CLOSE_TOO_BIG: + /* Send back the response */ + soup_websocket_connection_close (self, pv->peer_close_code, NULL); + break; + default: + g_debug ("Wrong closing code %d received", pv->peer_close_code); + } } } @@ -1632,7 +1710,6 @@ soup_websocket_connection_close (SoupWebsocketConnection *self, gushort code, const char *data) { - SoupWebsocketQueueFlags flags; SoupWebsocketConnectionPrivate *pv; g_return_if_fail (SOUP_IS_WEBSOCKET_CONNECTION (self)); @@ -1647,16 +1724,7 @@ soup_websocket_connection_close (SoupWebsocketConnection *self, else g_return_if_fail (code != SOUP_WEBSOCKET_CLOSE_SERVER_ERROR); - g_signal_emit (self, signals[CLOSING], 0); - - if (pv->close_received) - g_debug ("responding to close request"); - - flags = 0; - if (pv->connection_type == SOUP_WEBSOCKET_CONNECTION_SERVER && pv->close_received) - flags |= SOUP_WEBSOCKET_QUEUE_LAST; - send_close (self, flags, code, data); - close_io_after_timeout (self); + close_connection (self, code, data); } /** |