Skip to content

Commit

Permalink
Make the network code compile (#6262)
Browse files Browse the repository at this point in the history
* Make the network code compile

* Move WebSocketError definition to websocket.hpp

* WebSocket errors refactoring

* Introduce coarse-grained websocket errors to ErrorCodes::Error

* Replace RLM_SYNC_ERROR_CATEGORY_RESOLVE with RLM_SYNC_ERROR_CATEGORY_WEBSOCKET for sync errors in C API

* Fix object-store tests

* Fix wrong merge in sync_session.cpp

Co-authored-by: Daniel Tabacaru <daniel.tabacaru9@gmail.com>
  • Loading branch information
jedelbo and danieltabacaru authored Feb 24, 2023
1 parent ae58f29 commit 650865c
Show file tree
Hide file tree
Showing 17 changed files with 437 additions and 331 deletions.
39 changes: 3 additions & 36 deletions src/realm.h
Original file line number Diff line number Diff line change
Expand Up @@ -3319,7 +3319,7 @@ typedef enum realm_sync_error_category {
RLM_SYNC_ERROR_CATEGORY_CLIENT,
RLM_SYNC_ERROR_CATEGORY_CONNECTION,
RLM_SYNC_ERROR_CATEGORY_SESSION,
RLM_SYNC_ERROR_CATEGORY_RESOLVE,
RLM_SYNC_ERROR_CATEGORY_WEBSOCKET,

/**
* System error - POSIX errno, Win32 HRESULT, etc.
Expand All @@ -3343,15 +3343,6 @@ typedef enum realm_sync_error_action {
RLM_SYNC_ERROR_ACTION_CLIENT_RESET_NO_RECOVERY,
} realm_sync_error_action_e;

typedef enum realm_sync_error_resolve {
RLM_SYNC_ERROR_RESOLVE_HOST_NOT_FOUND = 1,
RLM_SYNC_ERROR_RESOLVE_HOST_NOT_FOUND_TRY_AGAIN = 2,
RLM_SYNC_ERROR_RESOLVE_NO_DATA = 3,
RLM_SYNC_ERROR_RESOLVE_NO_RECOVERY = 4,
RLM_SYNC_ERROR_RESOLVE_SERVICE_NOT_FOUND = 5,
RLM_SYNC_ERROR_RESOLVE_SOCKET_TYPE_NOT_SUPPORTED = 6,
} realm_sync_error_resolve_e;

typedef struct realm_sync_session realm_sync_session_t;
typedef struct realm_async_open_task realm_async_open_task_t;

Expand Down Expand Up @@ -4092,30 +4083,6 @@ RLM_API bool realm_mongo_collection_find_one_and_delete(realm_mongodb_collection
realm_userdata_t data, realm_free_userdata_func_t delete_data,
realm_mongodb_callback_t callback);

typedef enum status_error_code {
STATUS_OK = 0,
STATUS_UNKNOWN_ERROR = 1,
STATUS_RUNTIME_ERROR = 2,
STATUS_LOGIC_ERROR = 3,
STATUS_BROKEN_PROMISE = 4,
STATUS_OPERATION_ABORTED = 5,

/// WEBSOCKET ERRORS
// STATUS_WEBSOCKET_OK = 1000 IS NOT USED, JUST USE OK INSTEAD
STATUS_WEBSOCKET_GOING_AWAY = 1001,
STATUS_WEBSOCKET_PROTOCOL_ERROR = 1002,
STATUS_WEBSOCKET_UNSUPPORTED_DATA = 1003,
STATUS_WEBSOCKET_RESERVED = 1004,
STATUS_WEBSOCKET_NO_STATUS_RECEIVED = 1005,
STATUS_WEBSOCKET_ABNORMAL_CLOSURE = 1006,
STATUS_WEBSOCKET_INVALID_PAYLOAD_DATA = 1007,
STATUS_WEBSOCKET_POLICY_VIOLATION = 1008,
STATUS_WEBSOCKET_MESSAGE_TOO_BIG = 1009,
STATUS_WEBSOCKET_INAVALID_EXTENSION = 1010,
STATUS_WEBSOCKET_INTERNAL_SERVER_ERROR = 1011,
STATUS_WEBSOCKET_TLS_HANDSHAKE_FAILED = 1015, // USED BY DEFAULT WEBSOCKET
} status_error_code_e;

RLM_API realm_sync_socket_t* realm_sync_socket_new(
realm_userdata_t userdata, realm_free_userdata_func_t userdata_free, realm_sync_socket_post_func_t post_func,
realm_sync_socket_create_timer_func_t create_timer_func,
Expand All @@ -4125,7 +4092,7 @@ RLM_API realm_sync_socket_t* realm_sync_socket_new(
realm_sync_socket_websocket_free_func_t websocket_free_func);

RLM_API void realm_sync_socket_callback_complete(realm_sync_socket_callback_t* realm_callback,
status_error_code_e status, const char* reason);
realm_web_socket_errno_e status, const char* reason);

RLM_API void realm_sync_socket_websocket_connected(realm_websocket_observer_t* realm_websocket_observer,
const char* protocol);
Expand All @@ -4136,7 +4103,7 @@ RLM_API void realm_sync_socket_websocket_message(realm_websocket_observer_t* rea
const char* data, size_t data_size);

RLM_API void realm_sync_socket_websocket_closed(realm_websocket_observer_t* realm_websocket_observer, bool was_clean,
status_error_code_e status, const char* reason);
realm_web_socket_errno_e status, const char* reason);

RLM_API void realm_sync_client_config_set_sync_socket(realm_sync_client_config_t*,
realm_sync_socket_t*) RLM_API_NOEXCEPT;
Expand Down
30 changes: 6 additions & 24 deletions src/realm/error_codes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,18 +207,9 @@ ErrorCategory ErrorCodes::error_categories(Error code)
.set(ErrorCategory::app_error)
.set(ErrorCategory::service_error);

case WebSocketGoingAway:
case WebSocketProtocolError:
case WebSocketUnsupportedData:
case WebSocketReserved:
case WebSocketNoStatusReceived:
case WebSocketAbnormalClosure:
case WebSocketInvalidPayloadData:
case WebSocketPolicyViolation:
case WebSocketMessageTooBig:
case WebSocketInavalidExtension:
case WebSocketInternalServerError:
case WebSocketTLSHandshakeFailed:
case WebSocketResolveFailedError:
case WebSocketConnectionClosedClientError:
case WebSocketConnectionClosedServerError:
return ErrorCategory().set(ErrorCategory::runtime_error).set(ErrorCategory::websocket_error);

case UnknownError:
Expand Down Expand Up @@ -374,18 +365,9 @@ static const MapElem string_to_error_code[] = {
{"ValueAlreadyExists", ErrorCodes::ValueAlreadyExists},
{"ValueDuplicateName", ErrorCodes::ValueDuplicateName},
{"ValueNotFound", ErrorCodes::ValueNotFound},
{"WebSocketAbnormalClosure", ErrorCodes::WebSocketAbnormalClosure},
{"WebSocketGoingAway", ErrorCodes::WebSocketGoingAway},
{"WebSocketInavalidExtension", ErrorCodes::WebSocketInavalidExtension},
{"WebSocketInternalServerError", ErrorCodes::WebSocketInternalServerError},
{"WebSocketInvalidPayloadData", ErrorCodes::WebSocketInvalidPayloadData},
{"WebSocketMessageTooBig", ErrorCodes::WebSocketMessageTooBig},
{"WebSocketNoStatusReceived", ErrorCodes::WebSocketNoStatusReceived},
{"WebSocketPolicyViolation", ErrorCodes::WebSocketPolicyViolation},
{"WebSocketProtocolError", ErrorCodes::WebSocketProtocolError},
{"WebSocketReserved", ErrorCodes::WebSocketReserved},
{"WebSocketTLSHandshakeFailed", ErrorCodes::WebSocketTLSHandshakeFailed},
{"WebSocketUnsupportedData", ErrorCodes::WebSocketUnsupportedData},
{"WebSocketConnectionClosedClientError", ErrorCodes::WebSocketConnectionClosedClientError},
{"WebSocketConnectionClosedServerError", ErrorCodes::WebSocketConnectionClosedServerError},
{"WebSocketResolveFailedError", ErrorCodes::WebSocketResolveFailedError},
{"WrongThread", ErrorCodes::WrongThread},
{"WrongTransactionState", ErrorCodes::WrongTransactionState},
};
Expand Down
45 changes: 33 additions & 12 deletions src/realm/error_codes.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,18 +183,9 @@ typedef enum realm_errno {
RLM_ERR_MAINTENANCE_IN_PROGRESS = 4352,
RLM_ERR_USERPASS_TOKEN_INVALID = 4353,

RLM_ERR_WEBSOCKET_GOINGAWAY = 4400,
RLM_ERR_WEBSOCKET_PROTOCOLERROR = 4401,
RLM_ERR_WEBSOCKET_UNSUPPORTEDDATA = 4402,
RLM_ERR_WEBSOCKET_RESERVED = 4403,
RLM_ERR_WEBSOCKET_NOSTATUSRECEIVED = 4404,
RLM_ERR_WEBSOCKET_ABNORMALCLOSURE = 4405,
RLM_ERR_WEBSOCKET_INVALIDPAYLOADDATA = 4406,
RLM_ERR_WEBSOCKET_POLICYVIOLATION = 4407,
RLM_ERR_WEBSOCKET_MESSAGETOOBIG = 4408,
RLM_ERR_WEBSOCKET_INAVALIDEXTENSION = 4409,
RLM_ERR_WEBSOCKET_INTERNALSERVERERROR = 4410,
RLM_ERR_WEBSOCKET_TLSHANDSHAKEFAILED = 4411,
RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR = 4400,
RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR = 4401,
RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR = 4402,

RLM_ERR_CALLBACK = 1000000, /**< A user-provided callback failed. */
RLM_ERR_UNKNOWN = 2000000 /* Should not be used in code */
Expand Down Expand Up @@ -287,4 +278,34 @@ typedef enum realm_sync_errno_session {
RLM_SYNC_ERR_SESSION_BAD_PROGRESS = 233,
} realm_sync_errno_session_e;

typedef enum realm_web_socket_errno {
RLM_ERR_WEBSOCKET_OK = 1000,
RLM_ERR_WEBSOCKET_GOINGAWAY = 1001,
RLM_ERR_WEBSOCKET_PROTOCOLERROR = 1002,
RLM_ERR_WEBSOCKET_UNSUPPORTEDDATA = 1003,
RLM_ERR_WEBSOCKET_RESERVED = 1004,
RLM_ERR_WEBSOCKET_NOSTATUSRECEIVED = 1005,
RLM_ERR_WEBSOCKET_ABNORMALCLOSURE = 1006,
RLM_ERR_WEBSOCKET_INVALIDPAYLOADDATA = 1007,
RLM_ERR_WEBSOCKET_POLICYVIOLATION = 1008,
RLM_ERR_WEBSOCKET_MESSAGETOOBIG = 1009,
RLM_ERR_WEBSOCKET_INAVALIDEXTENSION = 1010,
RLM_ERR_WEBSOCKET_INTERNALSERVERERROR = 1011,
RLM_ERR_WEBSOCKET_TLSHANDSHAKEFAILED = 1015,

RLM_ERR_WEBSOCKET_UNAUTHORIZED = 4001,
RLM_ERR_WEBSOCKET_FORBIDDEN = 4002,
RLM_ERR_WEBSOCKET_MOVEDPERMANENTLY = 4003,
RLM_ERR_WEBSOCKET_CLIENT_TOO_OLD = 4004,
RLM_ERR_WEBSOCKET_CLIENT_TOO_NEW = 4005,
RLM_ERR_WEBSOCKET_PROTOCOL_MISMATCH = 4006,

RLM_ERR_WEBSOCKET_RESOLVE_FAILED = 4400,
RLM_ERR_WEBSOCKET_CONNECTION_FAILED = 4401,
RLM_ERR_WEBSOCKET_READ_ERROR = 4402,
RLM_ERR_WEBSOCKET_WRITE_ERROR = 4403,
RLM_ERR_WEBSOCKET_RETRY_ERROR = 4404,
RLM_ERR_WEBSOCKET_FATAL_ERROR = 4405,
} realm_web_socket_errno_e;

#endif /* REALM_ERROR_CODES_H */
31 changes: 3 additions & 28 deletions src/realm/error_codes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,34 +225,9 @@ class ErrorCodes {
AppUnknownError = RLM_ERR_APP_UNKNOWN,
MaintenanceInProgress = RLM_ERR_MAINTENANCE_IN_PROGRESS,
UserpassTokenInvalid = RLM_ERR_USERPASS_TOKEN_INVALID,

WebSocketGoingAway = RLM_ERR_WEBSOCKET_GOINGAWAY,
WebSocketProtocolError = RLM_ERR_WEBSOCKET_PROTOCOLERROR,
WebSocketUnsupportedData = RLM_ERR_WEBSOCKET_UNSUPPORTEDDATA,
WebSocketReserved = RLM_ERR_WEBSOCKET_RESERVED,
WebSocketNoStatusReceived = RLM_ERR_WEBSOCKET_NOSTATUSRECEIVED,
WebSocketAbnormalClosure = RLM_ERR_WEBSOCKET_ABNORMALCLOSURE,
WebSocketInvalidPayloadData = RLM_ERR_WEBSOCKET_INVALIDPAYLOADDATA,
WebSocketPolicyViolation = RLM_ERR_WEBSOCKET_POLICYVIOLATION,
WebSocketMessageTooBig = RLM_ERR_WEBSOCKET_MESSAGETOOBIG,
WebSocketInavalidExtension = RLM_ERR_WEBSOCKET_INAVALIDEXTENSION,
WebSocketInternalServerError = RLM_ERR_WEBSOCKET_INTERNALSERVERERROR,
WebSocketTLSHandshakeFailed = RLM_ERR_WEBSOCKET_TLSHANDSHAKEFAILED, // Used by default WebSocket

// HACK
ReadError,
WriteError,
ResolveFailed,
ConnectionFailed,
WebSocketRetryError,
WebSocketFatalError,
WebSocketUnauthorized,
WebSocketForbidden,
WebSocketMovedPermanently,
WebSocketClient_Too_Old,
WebSocketClient_Too_New,
WebSocketProtocol_Mismatch,
// HACK
WebSocketResolveFailedError = RLM_ERR_WEBSOCKET_RESOLVE_FAILED_ERROR,
WebSocketConnectionClosedClientError = RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_CLIENT_ERROR,
WebSocketConnectionClosedServerError = RLM_ERR_WEBSOCKET_CONNECTION_CLOSED_SERVER_ERROR,

CallbackFailed = RLM_ERR_CALLBACK,
UnknownError = RLM_ERR_UNKNOWN,
Expand Down
15 changes: 9 additions & 6 deletions src/realm/object-store/c_api/socket_provider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <realm/status.hpp>
#include <realm/object-store/c_api/util.hpp>
#include <realm/sync/socket_provider.hpp>
#include <realm/sync/network/websocket.hpp>

namespace realm::c_api {
namespace {
Expand Down Expand Up @@ -218,11 +219,12 @@ RLM_API realm_sync_socket_t* realm_sync_socket_new(
}

RLM_API void realm_sync_socket_callback_complete(realm_sync_socket_callback* realm_callback,
status_error_code_e status, const char* reason)
realm_web_socket_errno_e code, const char* reason)
{
auto complete_status = status == status_error_code_e::STATUS_OK
auto status = sync::websocket::WebSocketError(code);
auto complete_status = code == realm_web_socket_errno_e::RLM_ERR_WEBSOCKET_OK
? Status::OK()
: Status{static_cast<ErrorCodes::Error>(status), reason};
: Status{sync::websocket::make_error_code(status), reason};
(*(realm_callback->get()))(complete_status);
realm_release(realm_callback);
}
Expand All @@ -245,11 +247,12 @@ RLM_API void realm_sync_socket_websocket_message(realm_websocket_observer_t* rea
}

RLM_API void realm_sync_socket_websocket_closed(realm_websocket_observer_t* realm_websocket_observer, bool was_clean,
status_error_code_e status, const char* reason)
realm_web_socket_errno_e code, const char* reason)
{
auto closed_status = status == status_error_code_e::STATUS_OK
auto status = sync::websocket::WebSocketError(code);
auto closed_status = code == realm_web_socket_errno_e::RLM_ERR_WEBSOCKET_OK
? Status::OK()
: Status{static_cast<ErrorCodes::Error>(status), reason};
: Status{sync::websocket::make_error_code(status), reason};
realm_websocket_observer->get()->websocket_closed_handler(was_clean, closed_status);
}

Expand Down
21 changes: 5 additions & 16 deletions src/realm/object-store/c_api/sync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <realm/sync/config.hpp>
#include <realm/sync/client.hpp>
#include <realm/sync/protocol.hpp>
#include <realm/sync/network/network.hpp>
#include <realm/sync/network/websocket.hpp>
#include <realm/object-store/c_api/conversion.hpp>
#include <realm/object-store/sync/sync_manager.hpp>
#include <realm/object-store/sync/sync_session.hpp>
Expand Down Expand Up @@ -117,17 +117,6 @@ static_assert(realm_flx_sync_subscription_set_state_e(SubscriptionSet::State::Su
static_assert(realm_flx_sync_subscription_set_state_e(SubscriptionSet::State::Uncommitted) ==
RLM_SYNC_SUBSCRIPTION_UNCOMMITTED);

static_assert(realm_sync_error_resolve_e(network::ResolveErrors::host_not_found) ==
RLM_SYNC_ERROR_RESOLVE_HOST_NOT_FOUND);
static_assert(realm_sync_error_resolve_e(network::ResolveErrors::host_not_found_try_again) ==
RLM_SYNC_ERROR_RESOLVE_HOST_NOT_FOUND_TRY_AGAIN);
static_assert(realm_sync_error_resolve_e(network::ResolveErrors::no_data) == RLM_SYNC_ERROR_RESOLVE_NO_DATA);
static_assert(realm_sync_error_resolve_e(network::ResolveErrors::no_recovery) == RLM_SYNC_ERROR_RESOLVE_NO_RECOVERY);
static_assert(realm_sync_error_resolve_e(network::ResolveErrors::service_not_found) ==
RLM_SYNC_ERROR_RESOLVE_SERVICE_NOT_FOUND);
static_assert(realm_sync_error_resolve_e(network::ResolveErrors::socket_type_not_supported) ==
RLM_SYNC_ERROR_RESOLVE_SOCKET_TYPE_NOT_SUPPORTED);

} // namespace

realm_sync_error_code_t to_capi(const Status& status, std::string& message)
Expand All @@ -150,8 +139,8 @@ realm_sync_error_code_t to_capi(const Status& status, std::string& message)
else if (category == std::system_category() || category == realm::util::error::basic_system_error_category()) {
ret.category = RLM_SYNC_ERROR_CATEGORY_SYSTEM;
}
else if (category == realm::sync::network::resolve_error_category()) {
ret.category = RLM_SYNC_ERROR_CATEGORY_RESOLVE;
else if (category == realm::sync::websocket::websocket_error_category()) {
ret.category = RLM_SYNC_ERROR_CATEGORY_WEBSOCKET;
}
else {
ret.category = RLM_SYNC_ERROR_CATEGORY_UNKNOWN;
Expand Down Expand Up @@ -179,8 +168,8 @@ void sync_error_to_error_code(const realm_sync_error_code_t& sync_error_code, st
else if (category == RLM_SYNC_ERROR_CATEGORY_SYSTEM) {
error_code_out->assign(sync_error_code.value, std::system_category());
}
else if (category == RLM_SYNC_ERROR_CATEGORY_RESOLVE) {
error_code_out->assign(sync_error_code.value, realm::sync::network::resolve_error_category());
else if (category == RLM_SYNC_ERROR_CATEGORY_WEBSOCKET) {
error_code_out->assign(sync_error_code.value, realm::sync::websocket::websocket_error_category());
}
else if (category == RLM_SYNC_ERROR_CATEGORY_UNKNOWN) {
error_code_out->assign(sync_error_code.value, realm::util::error::basic_system_error_category());
Expand Down
5 changes: 5 additions & 0 deletions src/realm/object-store/sync/generic_network_transport.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ struct AppError : public RuntimeError {
{
return ErrorCodes::error_categories(code()).test(ErrorCategory::client_error);
}

bool is_websocket_error() const
{
return ErrorCodes::error_categories(code()).test(ErrorCategory::websocket_error);
}
};

std::ostream& operator<<(std::ostream& os, AppError error);
Expand Down
24 changes: 15 additions & 9 deletions src/realm/object-store/sync/sync_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -681,21 +681,27 @@ void SyncSession::handle_error(SyncError error)
break;
}
}
else {
else if (error_code.category() == sync::websocket::websocket_error_category()) {
// The server replies with '401: unauthorized' if the access token is invalid, expired, revoked, or the user
// is disabled. In this scenario we attempt an automatic token refresh and if that succeeds continue as
// normal. If the refresh request also fails with 401 then we need to stop retrying and pass along the error;
// see handle_refresh().
if (error_code.category() == sync::websocket::websocket_close_status_category()) {
bool restart_session = error_code.value() == ErrorCodes::WebSocketMovedPermanently;
if (restart_session || error_code.value() == ErrorCodes::WebSocketUnauthorized ||
error_code.value() == ErrorCodes::WebSocketAbnormalClosure) {
if (auto u = user()) {
u->refresh_custom_data(handle_refresh(shared_from_this(), restart_session));
return;
}
bool restart_session = error_code == sync::websocket::WebSocketError::websocket_moved_permanently;
if (restart_session || error_code == sync::websocket::WebSocketError::websocket_unauthorized ||
error_code == sync::websocket::WebSocketError::websocket_abnormal_closure) {
if (auto u = user()) {
u->refresh_custom_data(handle_refresh(shared_from_this(), restart_session));
return;
}
}

// Surface a simplified websocket error to the user.
auto simplified_error = sync::websocket::get_simplified_websocket_error(
static_cast<sync::websocket::WebSocketError>(error_code.value()));
std::error_code new_error_code(simplified_error, sync::websocket::websocket_error_category());
error = SyncError(new_error_code, error.reason(), error.is_fatal);
}
else {
// Unrecognized error code.
error.is_unrecognized_by_client = true;
}
Expand Down
Loading

0 comments on commit 650865c

Please sign in to comment.