Skip to content

Commit

Permalink
Implemented close correctly (#4002)
Browse files Browse the repository at this point in the history
* Implemented close correctly

* Code review feedback - made several classes inal.

* clang-format
  • Loading branch information
LarryOsterman authored Oct 11, 2022
1 parent b8330a1 commit b5dd9ef
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 25 deletions.
29 changes: 15 additions & 14 deletions sdk/core/azure-core/inc/azure/core/http/websockets/websockets.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ namespace Azure { namespace Core { namespace Http { namespace WebSockets {
* Note: Some of these statistics are not available if the underlying transport supports native
* websockets.
*/
struct WebSocketStatistics
struct WebSocketStatistics final
{
/** @brief The number of WebSocket frames sent on this WebSocket. */
uint32_t FramesSent;
Expand Down Expand Up @@ -172,11 +172,12 @@ namespace Azure { namespace Core { namespace Http { namespace WebSockets {
: FrameType{frameType}, IsFinalFrame{isFinalFrame}
{
}
virtual ~WebSocketFrame() {}
};

/** @brief Contains the contents of a WebSocket Text frame.*/
class WebSocketTextFrame : public WebSocketFrame,
public std::enable_shared_from_this<WebSocketTextFrame> {
class WebSocketTextFrame final : public WebSocketFrame,
public std::enable_shared_from_this<WebSocketTextFrame> {
friend Azure::Core::Http::WebSockets::_detail::WebSocketImplementation;

private:
Expand All @@ -201,8 +202,8 @@ namespace Azure { namespace Core { namespace Http { namespace WebSockets {
};

/** @brief Contains the contents of a WebSocket Binary frame.*/
class WebSocketBinaryFrame : public WebSocketFrame,
public std::enable_shared_from_this<WebSocketBinaryFrame> {
class WebSocketBinaryFrame final : public WebSocketFrame,
public std::enable_shared_from_this<WebSocketBinaryFrame> {
friend Azure::Core::Http::WebSockets::_detail::WebSocketImplementation;

private:
Expand All @@ -227,8 +228,9 @@ namespace Azure { namespace Core { namespace Http { namespace WebSockets {
};

/** @brief Contains the contents of a WebSocket Close frame.*/
class WebSocketPeerCloseFrame : public WebSocketFrame,
public std::enable_shared_from_this<WebSocketPeerCloseFrame> {
class WebSocketPeerCloseFrame final
: public WebSocketFrame,
public std::enable_shared_from_this<WebSocketPeerCloseFrame> {
friend Azure::Core::Http::WebSockets::_detail::WebSocketImplementation;

public:
Expand All @@ -254,7 +256,7 @@ namespace Azure { namespace Core { namespace Http { namespace WebSockets {
}
};

struct WebSocketOptions : Azure::Core::_internal::ClientOptions
struct WebSocketOptions final : Azure::Core::_internal::ClientOptions
{
/**
* @brief The set of protocols which are supported by this client
Expand Down Expand Up @@ -290,7 +292,7 @@ namespace Azure { namespace Core { namespace Http { namespace WebSockets {
WebSocketOptions() = default;
};

class WebSocket {
class WebSocket final {
public:
/** @brief Constructs a new instance of a WebSocket with the specified WebSocket options.
*
Expand All @@ -311,13 +313,12 @@ namespace Azure { namespace Core { namespace Http { namespace WebSockets {
*/
void Open(Azure::Core::Context const& context = Azure::Core::Context{});

/** @brief Closes a WebSocket connection to the remote server gracefully.
*
* @param context Context for the operation.
/** @brief Closes a WebSocket connection to the remote server.
*/
void Close(Azure::Core::Context const& context = Azure::Core::Context{});
void Close();

/** @brief Closes a WebSocket connection to the remote server with additional context.
/** @brief Gracefully closes a WebSocket connection to the remote server with additional
* context.
*
* @param closeStatus 16 bit WebSocket error code.
* @param closeReason String describing the reason for closing the socket.
Expand Down
8 changes: 7 additions & 1 deletion sdk/core/azure-core/src/http/curl/curl_websockets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@

namespace Azure { namespace Core { namespace Http { namespace WebSockets {

void CurlWebSocketTransport::Close() { m_upgradedConnection->Shutdown(); }
void CurlWebSocketTransport::Close()
{
if (m_upgradedConnection)
{
m_upgradedConnection->Shutdown();
}
}

// Send an HTTP request to the remote server.
std::unique_ptr<RawResponse> CurlWebSocketTransport::Send(
Expand Down
6 changes: 1 addition & 5 deletions sdk/core/azure-core/src/http/websockets/websockets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ namespace Azure { namespace Core { namespace Http { namespace WebSockets { names
{
m_socketImplementation->Open(context);
}
void WebSocket::Close(Azure::Core::Context const& context)
{
m_socketImplementation->Close(
static_cast<uint16_t>(WebSocketErrorCode::EndpointDisappearing), {}, context);
}
void WebSocket::Close() { m_socketImplementation->Close(); }
void WebSocket::Close(
uint16_t closeStatus,
std::string const& closeReason,
Expand Down
21 changes: 17 additions & 4 deletions sdk/core/azure-core/src/http/websockets/websockets_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ namespace Azure { namespace Core { namespace Http { namespace WebSockets { names
{
}

WebSocketImplementation::~WebSocketImplementation() { Close(); }

void WebSocketImplementation::Open(Azure::Core::Context const& context)
{
if (m_state != SocketState::Invalid && m_state != SocketState::Closed)
Expand Down Expand Up @@ -197,6 +199,19 @@ namespace Azure { namespace Core { namespace Http { namespace WebSockets { names
m_headers.emplace(std::make_pair(header, headerValue));
}

void WebSocketImplementation::Close()
{
std::unique_lock<std::mutex> lock(m_stateMutex);
m_stateOwner = std::this_thread::get_id();
// Close the socket - after this point, the m_transport is invalid.
m_pingThread.Shutdown();
if (m_transport)
{
m_transport->Close();
}
m_state = SocketState::Closed;
}

void WebSocketImplementation::Close(
uint16_t closeStatus,
std::string const& closeReason,
Expand Down Expand Up @@ -253,10 +268,8 @@ namespace Azure { namespace Core { namespace Http { namespace WebSockets { names
lock.lock();
m_stateOwner = std::this_thread::get_id();
}
// Close the socket - after this point, the m_transport is invalid.
m_pingThread.Shutdown();
m_transport->Close();
m_state = SocketState::Closed;
lock.unlock();
Close();
}

void WebSocketImplementation::SendFrame(
Expand Down
4 changes: 3 additions & 1 deletion sdk/core/azure-core/src/http/websockets/websockets_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace Azure { namespace Core { namespace Http { namespace WebSockets { names
// Generator for random bytes. Used in WebSocketImplementation and tests.
std::vector<uint8_t> GenerateRandomBytes(size_t vectorSize);

class WebSocketImplementation {
class WebSocketImplementation final {
enum class SocketState
{
Invalid,
Expand All @@ -30,8 +30,10 @@ namespace Azure { namespace Core { namespace Http { namespace WebSockets { names
WebSocketImplementation(
Azure::Core::Url const& remoteUrl,
_internal::WebSocketOptions const& options);
~WebSocketImplementation();

void Open(Azure::Core::Context const& context);
void Close();
void Close(
uint16_t closeStatus,
std::string const& closeReason,
Expand Down

0 comments on commit b5dd9ef

Please sign in to comment.