Skip to content

Conversation

@dudantas
Copy link
Collaborator

Description

Replaces in-house ASIO networking with ixwebsocket for HTTP and WebSocket. Removes duplicate transport code, unifies TLS handling, and reduces platform-specific branches.
CMake now finds and links ixwebsocket (and its TLS deps via package manager).
Public client APIs stay the same. Internal implementation changes only.

Dependencies:

  • Add: ixwebsocket (via vcpkg or system package), OpenSSL/Schannel as provided by ixwebsocket.
  • Remove: custom ASIO-based HTTP/WS code paths.

Behavior

Actual

  • Custom HTTP/WS stack is hard to maintain.
  • Reconnect and TLS edge cases vary by platform.
  • Windows setup is brittle and diverges from Linux/macOS.

Expected

  • Stable HTTP/WS with automatic reconnect and TLS handled by the library.
  • Consistent behavior on Windows, Linux, and macOS.
  • Smaller code surface and faster onboarding.

Type of change

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested

  • Built locally with vcpkg-provided ixwebsocket.

  • WebSocket echo test (open, send/receive, close).

  • Reconnect test (server drop to client auto-reconnect).

  • TLS handshake to a wss:// endpoint.

  • Manual test against the staging server for gameplay messages.

  • CI matrix on Windows, Ubuntu, macOS.

  • Test A: HTTP client requests succeed and validate status/body/headers

  • Test B: WebSocket connects, sends, receives, reconnects, and closes cleanly

Test Configuration:

  • Server Version: n/a
  • Client: otclient (this branch)
  • Operating System: Windows 11 23H2, Ubuntu 22.04, macOS 14

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I checked the PR checks reports
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works

Replaces custom ASIO-based HTTP and WebSocket implementations with ixwebsocket library for HTTP requests and WebSocket connections. Updates CMake configuration to include ixwebsocket, simplifies code, and improves maintainability and cross-platform support.
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
31.5% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@kokekanon
Copy link
Collaborator

kokekanon commented Sep 29, 2025

I was testing pr:

  • Compilation vs 2022 solution
  • Login http post myacc
  • api myacc
  • WebSocket
  • updater

1) compilation

compiling by solution (vs community 2022) it is not possible to compile.
My possible solution is to add this:
bcrypt.lib;
here

avrt.lib;

avrt.lib;

image

2) solve issues 1198

I confirm that this pr solves the issue #1198 mentioned by nekiro.

test with this in terminal :

local onRecvInfo = function(message, err) pdump(message)      end       HTTP.get("https://discord.com/api/v9/invites/WBMSR4qAzF?with_counts=true", onRecvInfo)
image

3) crash with websocket

The only easy way I have to test websock is with vbot. I'll look for a way to reproduce the crash more easily.

>	otclient_gl_x64.exe!abort() Line 77	C++
 	otclient_gl_x64.exe!terminate() Line 58	C++
 	otclient_gl_x64.exe!FindHandler<__FrameHandler4>(EHExceptionRecord * pExcept, unsigned __int64 * pRN, _CONTEXT * pContext, _xDISPATCHER_CONTEXT * pDC, FH4::FuncInfo4 * pFuncInfo, unsigned char recursive, int CatchDepth, unsigned __int64 * pMarkerRN) Line 739	C++
 	otclient_gl_x64.exe!__InternalCxxFrameHandler<__FrameHandler4>(EHExceptionRecord * pExcept, unsigned __int64 * pRN, _CONTEXT * pContext, _xDISPATCHER_CONTEXT * pDC, FH4::FuncInfo4 * pFuncInfo, int CatchDepth, unsigned __int64 * pMarkerRN, unsigned char recursive) Line 403	C++
 	otclient_gl_x64.exe!__InternalCxxFrameHandlerWrapper<__FrameHandler4>(EHExceptionRecord * pExcept, unsigned __int64 * pRN, _CONTEXT * pContext, _xDISPATCHER_CONTEXT * pDC, FH4::FuncInfo4 * pFuncInfo, int CatchDepth, unsigned __int64 * pMarkerRN, unsigned char recursive) Line 236	C++
 	otclient_gl_x64.exe!__CxxFrameHandler4(EHExceptionRecord * pExcept, unsigned __int64 RN, _CONTEXT * pContext, _xDISPATCHER_CONTEXT * pDC) Line 306	C++
 	otclient_gl_x64.exe!__GSHandlerCheck_EH4(_EXCEPTION_RECORD * ExceptionRecord, void * EstablisherFrame, _CONTEXT * ContextRecord, _DISPATCHER_CONTEXT * DispatcherContext) Line 86	C++
 	ntdll.dll!00007fff8830796f()	Unknown
 	ntdll.dll!00007fff88216397()	Unknown
 	ntdll.dll!00007fff883072ae()	Unknown
 	KernelBase.dll!00007fff85ad66ca()	Unknown
 	otclient_gl_x64.exe!_CxxThrowException(void * pExceptionObject, const _s__ThrowInfo * pThrowInfo) Line 82	C++
 	otclient_gl_x64.exe!std::_Throw_Cpp_error(int code) Line 35	C++
 	[Inline Frame] otclient_gl_x64.exe!std::thread::join() Line 130	C++
 	[Inline Frame] otclient_gl_x64.exe!ix::WebSocket::stop(unsigned short) Line 197	C++
 	otclient_gl_x64.exe!ix::WebSocket::~WebSocket() Line 61	C++
 	[Inline Frame] otclient_gl_x64.exe!std::_Ref_count_base::_Decref() Line 1149	C++
 	[Inline Frame] otclient_gl_x64.exe!std::_Ptr_base<Creature>::_Decref() Line 1366	C++
 	[Inline Frame] otclient_gl_x64.exe!std::shared_ptr<Creature>::{dtor}() Line 1650	C++
 	[Inline Frame] otclient_gl_x64.exe!std::destroy_at(std::pair<unsigned int const ,std::shared_ptr<Creature>> * const) Line 324	C++
 	[Inline Frame] otclient_gl_x64.exe!std::_Default_allocator_traits<std::allocator<std::_List_node<std::pair<unsigned int const ,std::shared_ptr<Creature>>,void *>>>::destroy(std::allocator<std::_List_node<std::pair<unsigned int const ,std::shared_ptr<Creature>>,void *>> &) Line 734	C++
 	otclient_gl_x64.exe!std::_List_node<std::pair<unsigned int const ,std::shared_ptr<Creature>>,void *>::_Freenode<std::allocator<std::_List_node<std::pair<unsigned int const ,std::shared_ptr<Creature>>,void *>>>(std::allocator<std::_List_node<std::pair<unsigned int const ,std::shared_ptr<Creature>>,void *>> & _Ptr, std::_List_node<std::pair<unsigned int const ,std::shared_ptr<Creature>>,void *> * _Al) Line 317	C++
 	[Inline Frame] otclient_gl_x64.exe!std::list<std::pair<int const ,std::shared_ptr<ix::WebSocket>>,std::allocator<std::pair<int const ,std::shared_ptr<ix::WebSocket>>>>::_Unchecked_erase(std::_List_node<std::pair<int const ,std::shared_ptr<ix::WebSocket>>,void *> * const) Line 1425	C++
 	[Inline Frame] otclient_gl_x64.exe!std::_Hash<std::_Umap_traits<int,std::shared_ptr<ix::WebSocket>,std::_Uhash_compare<int,std::hash<int>,std::equal_to<int>>,std::allocator<std::pair<int const ,std::shared_ptr<ix::WebSocket>>>,0>>::_Erase(const int &) Line 1112	C++
 	[Inline Frame] otclient_gl_x64.exe!std::_Hash<std::_Umap_traits<int,std::shared_ptr<ix::WebSocket>,std::_Uhash_compare<int,std::hash<int>,std::equal_to<int>>,std::allocator<std::pair<int const ,std::shared_ptr<ix::WebSocket>>>,0>>::erase(const int &) Line 1136	C++
 	otclient_gl_x64.exe!Http::ws::__l2::<lambda_1>::operator()(const std::unique_ptr<ix::WebSocketMessage,std::default_delete<ix::WebSocketMessage>> & msg) Line 418	C++
 	[Inline Frame] otclient_gl_x64.exe!std::_Func_class<void,std::unique_ptr<ix::WebSocketMessage,std::default_delete<ix::WebSocketMessage>> const &>::operator()(const std::unique_ptr<ix::WebSocketMessage,std::default_delete<ix::WebSocketMessage>> &) Line 951	C++
 	otclient_gl_x64.exe!ix::WebSocket::{ctor}::__l2::<lambda>(unsigned short code, const std::string & reason, unsigned __int64 wireSize, bool remote) Line 49	C++
 	[Inline Frame] otclient_gl_x64.exe!std::_Func_class<void,unsigned short,std::string const &,unsigned __int64,bool>::operator()(unsigned short <_Args_0>, const std::string & <_Args_1>, unsigned __int64 <_Args_2>, bool <_Args_3>) Line 951	C++
 	otclient_gl_x64.exe!ix::WebSocketTransport::setReadyState(ix::WebSocketTransport::ReadyState readyState) Line 217	C++
 	otclient_gl_x64.exe!ix::WebSocketTransport::dispatch(ix::WebSocketTransport::PollResult pollResult, const std::function<void __cdecl(std::string const &,unsigned __int64,bool,enum ix::WebSocketTransport::MessageKind)> & onMessageCallback) Line 723	C++
 	otclient_gl_x64.exe!ix::WebSocket::run() Line 401	C++
 	[Inline Frame] otclient_gl_x64.exe!std::invoke(int(*)(ALCcontext *) &&) Line 1739	C++
 	otclient_gl_x64.exe!std::thread::_Invoke<std::tuple<int (__cdecl*)(ALCcontext *),ALCcontext *>,0,1>(void * _RawVals) Line 61	C++
 	otclient_gl_x64.exe!thread_start<unsigned int (__cdecl*)(void *),1>(void * const parameter) Line 97	C++
 	kernel32.dll!00007fff8707e8d7()	Unknown
 	ntdll.dll!00007fff881a8d9c()	Unknown

image

Possible solution ?

0001-test.patch
It's made with AI. But it works xD . I'm not good at c++.
me test

Http::ws [5] received message (119 bytes, binary=false, wireSize=119, preview='{"id":247582369,"message":["Paladin Sample","Sorcerer Sample"],"name":"Paladin Sample","topic":"list","type":"message"}')
Http::ws [5] event Message (wireSize=26)
Http::ws [5] received message (26 bytes, binary=false, wireSize=26, preview='{"type":"ping","ping":243}')
Http::wsSend [5] sending 15 bytes (readyState=OPEN buffered=0)
Http::wsSend [5] sent 15 bytes (wireSize=15 compressionError=false)
Http::ws [5] event Message (wireSize=26)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants