Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the network code compile #6262

Merged
merged 13 commits into from
Feb 24, 2023
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);
}
Comment on lines +702 to +703
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also set error.is_unrecognized_by_client = true;, since this was being done before.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should not be a problem, since these errors (coarse-grained websocket errors) are recognized by the client

else {
// Unrecognized error code.
error.is_unrecognized_by_client = true;
}
Expand Down
Loading