Conversation
- Removed boost-* dependencies from vcpkg.json and integrated standalone asio. - Cleaned up CMake build files, removing FindBoost.cmake and Boost configurations. - Migrated boost::asio and boost::system::error_code usages to standalone asio. - Re-implemented HTTP/HTTPS (HttpSession) and WebSocket/WSS (WebsocketSession) using standalone asio + OpenSSL/SSL stream, removing boost::beast entirely. - Replaced boost::filesystem with std::filesystem. - Replaced boost::uuids with a custom name-generator UUIDv5 implementation to preserve exact decrypter compatibility. - Replaced boost::process with native Windows (CreateProcessW) and Unix (fork/waitpid) process execution. - Replaced boost::tokenizer in OTML parsing with a lightweight native CSV-style parser. - Replaced boost::algorithm::unhex with a standard hexadecimal to binary conversion helper. - Removed boost includes from pch.h and defined ASIO_STANDALONE.
WalkthroughEste PR substitui Boost.Asio por Asio standalone em toda a rede assíncrona, reimplementa HTTP/WebSocket sem Boost.Beast, remove outras dependências Boost (UUID, strings, processos), atualiza build para C++23, com mudanças sistemáticas a arquivos de cliente, framework e configuração. ChangesMigração Asio e Remoção de Dependências Boost
Configurações de Build e Ferramentas
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
There was a problem hiding this comment.
Actionable comments posted: 18
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/framework/CMakeLists.txt (1)
171-171:⚠️ Potential issue | 🟠 Major | ⚡ Quick winAlinhe o padrão C++ do CMake com o
.vcxprojO CMake continua fixando
CMAKE_CXX_STANDARDem 17 (src/framework/CMakeLists.txt:171e tambémCMakeLists.txt:8), enquanto o Visual Studiovc23/otclient.vcxprojusa<LanguageStandard>stdcpp23</LanguageStandard>. Isso cria builds inconsistentes e pode quebrar código esperado para C++23 ao compilar via CMake.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/framework/CMakeLists.txt` at line 171, Atualize a definição do padrão C++ nos CMakeLists onde aparece set(CMAKE_CXX_STANDARD 17) para usar 23 (CMAKE_CXX_STANDARD 23) e force o comportamento consistente adicionando também set(CMAKE_CXX_STANDARD_REQUIRED ON) e set(CMAKE_CXX_EXTENSIONS OFF) próximo a essas linhas; corrija ambas as ocorrências do CMakeLists para alinhar com o LanguageStandard usado no projeto (referência: o símbolo CMAKE_CXX_STANDARD e onde é definido).src/framework/core/application.cpp (1)
183-197:⚠️ Potential issue | 🟠 Major | ⚡ Quick winGarantir relançamento antes de encerrar o processo (restart/restartArgs)
Application::restart()eApplication::restartArgs()chamamg_platform.spawnProcess(...)e depois fazemquick_exit()sem checar o retorno. No Unix (src/framework/platform/unixplatform.cpp),spawnProcess(...)retornaboole implementafork()/exec— sespawnProcesspuder retornarfalse(ou não conseguir iniciar o processo filho), o processo atual ainda assim é finalizado, impedindo o relançamento. No Android,spawnProcess(...)explicitamente retornafalse, mas emsrc/framework/core/application.cppo ramoANDROIDfazexit()(logo não há tentativa de relançamento viaspawnProcess). Revisar a lógica para só encerrar o processo atual quando o spawn indicar sucesso (e/ou introduzir fallback/erro no caso de falha).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/framework/core/application.cpp` around lines 183 - 197, Application::restart() and Application::restartArgs() call g_platform.spawnProcess(...) and immediately call quick_exit()/exit() without checking the bool result; change both to call spawnProcess(...) and only call quick_exit() (or exit()) if spawnProcess returns true. If spawnProcess returns false, do not terminate the current process; instead log or report the failure and return so the caller remains running (also handle the ANDROID branch by avoiding unconditional exit when spawnProcess fails). Update the code paths around g_platform.spawnProcess, Application::restart, Application::restartArgs, quick_exit, and exit to implement this conditional behavior.src/framework/proxy/proxy_client.cpp (1)
427-434:⚠️ Potential issue | 🟠 Major | ⚡ Quick winEntregue o pacote drenado da fila, não o último pacote recebido.
Quando o gap fecha e o
whilelibera mais de um item, o callback recebepacketem todas as iterações. Isso duplica o payload recém-chegado e descarta os pacotes que já estavam bufferizados emm_sendQueue.💡 Ajuste sugerido
if (!m_useSocket) { while (!m_sendQueue.empty() && m_sendQueue.begin()->first == m_inputPacketId) { + const auto& queuedPacket = m_sendQueue.begin()->second; m_inputPacketId += 1; if (m_recvCallback) { - m_recvCallback(packet); + m_recvCallback(queuedPacket); } m_sendQueue.erase(m_sendQueue.begin()); } return; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/framework/proxy/proxy_client.cpp` around lines 427 - 434, O loop que fecha o gap está chamando m_recvCallback com a variável externa packet em todas as iterações, duplicando o último pacote e ignorando os itens reais da fila; em vez disso, atue sobre o item drenado da fila: dentro do while em proxy_client.cpp use o elemento obtido de m_sendQueue.begin() (por exemplo uma cópia ou referência chamada queuedPacket) ao atualizar m_inputPacketId, chame m_recvCallback(queuedPacket) e só então erase(m_sendQueue.begin()), garantindo que cada pacote bufferizado seja entregue uma vez; mantenha as verificações de m_useSocket, m_sendQueue, m_inputPacketId e m_recvCallback intactas.
🧹 Nitpick comments (2)
src/client/tile.cpp (1)
994-994: 💤 Low valueConsidere manter o argumento de template explícito para maior clareza.
A remoção de
<int>destd::abs<int>(...)funciona corretamente, mas o template explícito tornava a intenção mais clara e protegia contra resoluções de sobrecarga inesperadas. Recomenda-se restaurarstd::abs<int>para melhor legibilidade.♻️ Sugestão de reversão
- if(distance > 0 && std::max<int>(std::abs(m_position.x - playerPos.x), std::abs(m_position.y - playerPos.y)) > distance) + if(distance > 0 && std::max<int>(std::abs<int>(m_position.x - playerPos.x), std::abs<int>(m_position.y - playerPos.y)) > distance)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/client/tile.cpp` at line 994, Restore the explicit template argument on std::abs to make the intent clear and avoid overload surprises: change the expression using std::abs in the conditional that compares m_position and playerPos (the line with if(distance > 0 && std::max<int>(std::abs(m_position.x - playerPos.x), std::abs(m_position.y - playerPos.y)) > distance)) back to std::abs<int>(...) for both x and y so the max<int> comparison remains unambiguous.src/client/animatedtext.cpp (1)
96-96: 💤 Low valueConsidere usar literal float para maior consistência.
A expressão
(float)Otc::ANIMATED_TEXT_DURATION / 2.5funciona corretamente, mas mistura um cast explícito parafloatcom um literal double (2.5). Para maior clareza e consistência de tipos, considere usar2.5fem vez de2.5.♻️ Refatoração sugerida
- if(m_animationTimer.ticksElapsed() > (float)Otc::ANIMATED_TEXT_DURATION / 2.5) + if(m_animationTimer.ticksElapsed() > Otc::ANIMATED_TEXT_DURATION / 2.5f)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/client/animatedtext.cpp` at line 96, The comparison mixes an explicit float cast with a double literal; update the right-hand side to use a float literal (e.g., replace 2.5 with 2.5f) so the expression (float)Otc::ANIMATED_TEXT_DURATION / 2.5f has consistent float types when used in the if condition that compares m_animationTimer.ticksElapsed().
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/framework/CMakeLists.txt`:
- Line 176: O ramo WASM em src/framework/CMakeLists.txt não fornece os headers
do Asio usados por src/framework/pch.h (que define ASIO_STANDALONE e inclui
<asio.hpp>/<asio/ssl.hpp>), causando falha no preprocessamento; corrija o bloco
if(WASM) para expor os headers do Asio — ou habilite o uso dos headers Boost e
ajuste includes — adicionando a mesma configuração de include/directories usada
quando find_package(asio CONFIG REQUIRED) roda (ou alternadamente definir -s
USE_BOOST_HEADERS=1 e apontar para os include paths de boost/asio), garantindo
que pch.h encontre <asio.hpp> durante a compilação.
In `@src/framework/http/session.cpp`:
- Around line 152-155: Normalize header names and transfer-coding comparisons to
be case-insensitive: when populating or using m_headers (the parsed header map),
convert header names to a canonical form (e.g., lowercase) so lookups like the
Location extraction (currently checking "Location" and "location") work
reliably, and when checking transfer-encoding/transfer-coding values (the parser
that marks chunked when value == "chunked") compare lowercased values or
otherwise perform case-insensitive comparison; update the header-parsing code
that fills m_headers and the places that read Location and
Transfer-Encoding/Transfer-Coding to use the canonical/lowercased keys and
lowercased value comparisons (affecting the Location lookup and the
chunked-detection logic).
- Around line 316-331: The timeout is lost after the first chunk because calling
m_timer.expires_after(...) cancels any pending async_wait; you must re-arm the
wait after resetting the timer. Update the read logic (around m_timer,
m_timer.expires_after, and the async_read_some callers in the session code that
invoke on_read_body) so each new expires_after(...) is followed by a matching
m_timer.async_wait(...) registration (or centralize into a
start_read_with_timeout helper that calls m_timer.expires_after(...) then
m_timer.async_wait(...) and then the appropriate async_read_some on m_ssl or
m_socket), ensuring the timer's handler will cancel the socket/stream on timeout
and that the async_wait is re-registered for every subsequent chunk.
- Around line 91-95: The current verify callback on m_ssl
(m_ssl->set_verify_callback(...)) unconditionally returns true and disables TLS
verification; replace this with proper verification by removing the permissive
lambda and using the platform verifier (keep
m_ssl->set_verify_mode(asio::ssl::verify_peer)) plus either call
m_ssl->set_verify_callback(asio::ssl::rfc2818_verification(hostname)) with the
server hostname, or implement a callback that returns (preverified &&
host-name-check) where you inspect the X509 certificate (e.g., using
X509_check_host or equivalent) to ensure the certificate matches the expected
hostname; update the code paths that construct m_ssl to accept/propagate the
server hostname so rfc2818_verification or host checks can be used.
In `@src/framework/http/session.h`:
- Around line 63-64: A assinatura de HttpSession::on_resolve está errada: o
handler de m_resolver.async_resolve(m_domain, std::to_string(m_port), ...)
recebe asio::ip::tcp::resolver::results_type, não resolver::iterator, então
altere HttpSession::on_resolve para aceitar const
asio::ip::tcp::resolver::results_type& results (ou results_type) e adapte o
corpo correspondente; no .cpp, substitua a lógica que usava
m_socket.async_connect(*iterator, ...) por asio::async_connect(m_socket,
results, /* bind your existing connect handler */) e remova/pare de ajustar
iterator->endpoint().port(m_port) já que a porta/serviço foi passada ao
async_resolve; mantenha nomes existentes (m_resolver, m_socket, on_resolve,
on_connect) ao aplicar a correção.
In `@src/framework/http/websocket.cpp`:
- Around line 104-105: Substitua o uso de um Sec-WebSocket-Key fixo e a simples
busca por "101" por um handshake correto: gere um nonce aleatório por conexão,
base64-encode e escreva-o no header "Sec-WebSocket-Key", calcule o valor
esperado de "Sec-WebSocket-Accept" usando SHA1(nonce +
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11") e base64-encode do hash, e ao ler a
resposta verifique explicitamente que o status é 101 e que os headers "Upgrade:
websocket", "Connection: Upgrade" e "Sec-WebSocket-Accept" estão presentes e que
o valor de "Sec-WebSocket-Accept" bate com o esperado; atualize o código que
escreve o header "Sec-WebSocket-Key" e a lógica que atualmente apenas procura a
substring "101" para usar essas verificações robustas.
- Around line 108-114: A vida útil de req_str em
WebsocketSession::do_handshake() não é garantida para a operação assíncrona: em
vez de passar o buffer de uma std::string local para asio::async_write
(m_ssl/m_socket), armazene a requisição como membro (ex.: add m_handshake_req:
std::string e usar asio::buffer(m_handshake_req) ao chamar asio::async_write) ou
crie um std::shared_ptr<std::string> (auto req_ptr =
std::make_shared<std::string>(req.str())) e capture esse req_ptr no handler (use
um lambda que chama on_handshake_sent(shared_from_this(), ec) ou std::bind com
captura do req_ptr) para garantir que os dados permaneçam válidos até
on_handshake_sent ser chamado.
- Around line 302-310: O buffer local `frame` em WebsocketSession::do_write() é
destruído antes de o async_write completar, causando uso-after-free; altere para
alocar o payload como std::shared_ptr<std::vector<uint8_t>> (por exemplo
capturando-o numa variável shared_ptr chamada frame_ptr obtida de
buildWebSocketFrame), passe asio::buffer(*frame_ptr) para asio::async_write
(tanto no ramo m_ssl quanto m_socket) e capture esse frame_ptr no bind/handler
de modo que o recurso só seja liberado no final de WebsocketSession::on_write();
mantenha a lógica atual de desempilhar m_sendQueue dentro de on_write() e
garanta que on_write() libere a captura ao retornar.
- Around line 41-44: The TLS verification is effectively disabled and there are
lifetime/validation bugs: replace the lambda in m_ssl->set_verify_callback(...)
with proper certificate/hostname verification or remove it so verify_peer
enforces CA/hostname checks (use platform verification helpers), and ensure
m_ssl (asio::ssl::stream) performs a real TLS handshake before using WSS; in
do_handshake() validate the server response fully by computing and checking
Sec-WebSocket-Accept against the Sec-WebSocket-Key rather than just searching
for "101" (refer to Sec-WebSocket-Key and Sec-WebSocket-Accept handling), and
fix UAF/UB by ensuring buffers passed to asio::async_write (the local req_str
and local frame vector used in do_handshake() and do_write()) outlive the async
operation — e.g., move them into owned member buffers or use shared_ptr to
heap-allocate and bind them to the async handler so the data remains valid until
the write completes (references: m_ssl, set_verify_callback, do_handshake,
do_write, asio::async_write, asio::buffer).
In `@src/framework/http/websocket.h`:
- Around line 64-65: A assinatura de on_resolve está incorreta:
m_resolver.async_resolve(m_domain, std::to_string(m_port), ...) invoca o handler
com asio::ip::tcp::resolver::results_type, não resolver::iterator; altere a
declaração/definição de on_resolve para receber const
asio::ip::tcp::resolver::results_type& results (em vez de resolver::iterator), e
dentro de on_resolve atualize o uso que fazia
iterator->endpoint()/async_connect(*iterator, ...) para usar results (por
exemplo auto it = results.begin(); use it->endpoint() ou passe results
diretamente para m_socket.async_connect / asio::async_connect conforme a API
usada) assegurando que on_connect mantém assinatura void on_connect(const
asio::error_code& ec).
In `@src/framework/net/connection.cpp`:
- Around line 314-317: A chamada atual a m_socket.remote_endpoint() assume IPv4
e usa ip.address().to_v4().to_ulong(), o que lança em endpoints IPv6; update
getIp() (the code around m_socket.remote_endpoint / ip) to first check
ip.address().is_v4() (and optionally ip.address().is_v4_mapped()), only call
to_v4().to_ulong() for true cases, and provide a safe fallback for IPv6 (e.g.
return 0 or handle mapped-v4 conversion) so the function fails gracefully
instead of throwing.
In `@src/framework/net/packet_player.cpp`:
- Around line 12-23: The custom_unhex function must validate packetHex before
decoding: ensure the input length is even and contains only hex digits, and
detect conversion failures by using strtol's endptr (or equivalent) to verify
each byte token was fully parsed; on any validation or conversion error return
an error/empty optional or throw so callers (e.g., where packetHex is passed at
the call sites around lines 38-39) can abort replay instead of producing
truncated/corrupted packets. Update custom_unhex to perform these checks and
change its return/signature or error handling as needed so callers handle the
failure explicitly.
In `@src/framework/otml/otmlparser.cpp`:
- Around line 192-213: The tokenizer in otmlparser.cpp is dropping quote marks
and backslashes (variables: tokens, current, in_quotes, escaped) so
OTMLNode::value<std::string> never sees a quoted/raw value to unescape; change
the loop so that when a backslash is seen you append the backslash to current
and set escaped for the next char (instead of swallowing it), when an escaped
char is processed append that char (so the sequence stays "\x"), and when
encountering a quote toggle in_quotes but also append the '"' to current (so
quoted boundaries are preserved in the token); keep the comma-splitting behavior
(push_back current on comma when !in_quotes) and only clear current after
pushing.
In `@src/framework/proxy/proxy_client.cpp`:
- Around line 35-41: terminate() currently only closes the socket and cancels
the timer but leaves in-flight async operations (e.g., async_resolve,
async_connect) able to complete and re-mark the proxy connected; update
terminate() and related callback code (callbacks started in the
async_resolve/async_connect flow) to: set m_terminated = true, cancel any
pending resolver and socket operations (call cancel() on the resolver and
shutdown/close the socket with error handling), ensure callbacks check
m_terminated before mutating state or re-adding to g_proxies, and use
weak_ptr/owned self pattern in those callbacks to avoid resurrecting the object
after termination; apply the same fixes to the other similar block(s) referenced
around the 94-136 region so all pending async operations are cancelled and
guarded by m_terminated checks.
In `@src/framework/stdext/net.cpp`:
- Around line 30-38: The code uses
asio::detail::socket_ops::network_to_host_long and host_to_network_long in
ip_to_string and string_to_ip (affecting listSubnetAddresses) which relies on
non-public APIs; replace those calls with standard endianness conversions such
as ntohl/htonl (or a local stdext endian helper / boost::endian equivalent) so
endianness conversion no longer depends on asio::detail. Update ip_to_string to
call ntohl on the IPv4 uint32 before constructing asio::ip::address_v4, and
update string_to_ip to call htonl on address_v4.to_uint() before returning;
ensure any other occurrences (e.g., listSubnetAddresses) are changed the same
way.
In `@src/framework/ui/uitranslator.cpp`:
- Around line 29-30: A entrada em 'aligment' só remove espaços ' ' mas deixa
tabs/newlines/carriage returns, causando fallback para AlignNone/AnchorNone;
antes do mapeamento aplique normalização completa de whitespace (usar
stdext::trim ou remover todos os caracteres onde std::isspace(c) é true), então
chame stdext::tolower(aligment) e continue; refatore as ocorrências em que
'aligment' é processado (mesmo padrão citado nas linhas 54-55) para usar a mesma
normalização usada por translateState e translateAutoFocusPolicy.
In `@src/framework/util/crypt.cpp`:
- Around line 254-261: In Crypt::getCryptKey the code serializes a
platform-dependent std::size_t seed into key via key.assign((const
char*)&seed,...), causing size/endian variability; instead convert the computed
seed into a fixed-size integer (e.g., uint64_t or a fixed 16-byte buffer derived
from the seed), then explicitly serialize it to bytes in a defined byte order
(big-endian or little-endian using shifts/masks) and assign those bytes to key
before passing to xorCrypt; update references to seed in getCryptKey to use the
fixed-size value and ensure xorCrypt always receives the same-length,
order-deterministic key.
In `@vc23/otclient.vcxproj`:
- Line 42: O ficheiro vc23/otclient.vcxproj define PlatformToolset como v145 em
várias entradas; atualiza a documentação e a pipeline para garantir que o Visual
Studio 2026 / Build Tools com MSVC toolset v145 é instalado antes do MSBuild, ou
altere as entradas PlatformToolset (ex.: as tags PlatformToolset que contêm
"v145") para um toolset alternativo suportado pela CI (por exemplo v142) e
documenta o requisito mínimo de build na README/CI config para evitar falhas de
MSBuild.
---
Outside diff comments:
In `@src/framework/CMakeLists.txt`:
- Line 171: Atualize a definição do padrão C++ nos CMakeLists onde aparece
set(CMAKE_CXX_STANDARD 17) para usar 23 (CMAKE_CXX_STANDARD 23) e force o
comportamento consistente adicionando também set(CMAKE_CXX_STANDARD_REQUIRED ON)
e set(CMAKE_CXX_EXTENSIONS OFF) próximo a essas linhas; corrija ambas as
ocorrências do CMakeLists para alinhar com o LanguageStandard usado no projeto
(referência: o símbolo CMAKE_CXX_STANDARD e onde é definido).
In `@src/framework/core/application.cpp`:
- Around line 183-197: Application::restart() and Application::restartArgs()
call g_platform.spawnProcess(...) and immediately call quick_exit()/exit()
without checking the bool result; change both to call spawnProcess(...) and only
call quick_exit() (or exit()) if spawnProcess returns true. If spawnProcess
returns false, do not terminate the current process; instead log or report the
failure and return so the caller remains running (also handle the ANDROID branch
by avoiding unconditional exit when spawnProcess fails). Update the code paths
around g_platform.spawnProcess, Application::restart, Application::restartArgs,
quick_exit, and exit to implement this conditional behavior.
In `@src/framework/proxy/proxy_client.cpp`:
- Around line 427-434: O loop que fecha o gap está chamando m_recvCallback com a
variável externa packet em todas as iterações, duplicando o último pacote e
ignorando os itens reais da fila; em vez disso, atue sobre o item drenado da
fila: dentro do while em proxy_client.cpp use o elemento obtido de
m_sendQueue.begin() (por exemplo uma cópia ou referência chamada queuedPacket)
ao atualizar m_inputPacketId, chame m_recvCallback(queuedPacket) e só então
erase(m_sendQueue.begin()), garantindo que cada pacote bufferizado seja entregue
uma vez; mantenha as verificações de m_useSocket, m_sendQueue, m_inputPacketId e
m_recvCallback intactas.
---
Nitpick comments:
In `@src/client/animatedtext.cpp`:
- Line 96: The comparison mixes an explicit float cast with a double literal;
update the right-hand side to use a float literal (e.g., replace 2.5 with 2.5f)
so the expression (float)Otc::ANIMATED_TEXT_DURATION / 2.5f has consistent float
types when used in the if condition that compares
m_animationTimer.ticksElapsed().
In `@src/client/tile.cpp`:
- Line 994: Restore the explicit template argument on std::abs to make the
intent clear and avoid overload surprises: change the expression using std::abs
in the conditional that compares m_position and playerPos (the line with
if(distance > 0 && std::max<int>(std::abs(m_position.x - playerPos.x),
std::abs(m_position.y - playerPos.y)) > distance)) back to std::abs<int>(...)
for both x and y so the max<int> comparison remains unambiguous.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f9b615d4-4eaa-44ef-9018-af0a0002c08e
⛔ Files ignored due to path filters (2)
vc17/.vs/otclient/v18/Insiders/Browse.VC.dbis excluded by!**/*.dbvc17/.vs/otclient/v18/fileList.binis excluded by!**/*.bin
📒 Files selected for processing (56)
src/client/animatedtext.cppsrc/client/game.cppsrc/client/game.hsrc/client/minimap.cppsrc/client/protocolgame.cppsrc/client/protocolgame.hsrc/client/tile.cppsrc/framework/CMakeLists.txtsrc/framework/cmake/FindBoost.cmakesrc/framework/core/application.cppsrc/framework/core/filestream.cppsrc/framework/core/resourcemanager.cppsrc/framework/http/http.cppsrc/framework/http/http.hsrc/framework/http/session.cppsrc/framework/http/session.hsrc/framework/http/websocket.cppsrc/framework/http/websocket.hsrc/framework/net/connection.cppsrc/framework/net/connection.hsrc/framework/net/declarations.hsrc/framework/net/packet_player.cppsrc/framework/net/packet_player.hsrc/framework/net/protocol.cppsrc/framework/net/protocol.hsrc/framework/net/server.cppsrc/framework/otml/otmlparser.cppsrc/framework/pch.hsrc/framework/platform/win32platform.cppsrc/framework/proxy/proxy.cppsrc/framework/proxy/proxy.hsrc/framework/proxy/proxy_client.cppsrc/framework/proxy/proxy_client.hsrc/framework/sound/streamsoundsource.cppsrc/framework/stdext/net.cppsrc/framework/stdext/string.cppsrc/framework/stdext/uri.cppsrc/framework/ui/uitranslator.cppsrc/framework/util/crypt.cppsrc/framework/util/crypt.hsrc/framework/xml/tinyxml.cppvc17/.vs/otclient/FileContentIndex/19a69103-ba74-4359-9b41-6dd0d822002c.vsidxvc17/.vs/otclient/FileContentIndex/77044220-7347-4942-b64b-f8adb883e8d6.vsidxvc17/.vs/otclient/FileContentIndex/9072a3e2-26b5-4363-9356-df58c8ca6583.vsidxvc17/.vs/otclient/v18/.suovc17/.vs/otclient/v18/DocumentLayout.backup.jsonvc17/.vs/otclient/v18/DocumentLayout.jsonvc17/.vs/otclient/v18/Insiders/Browse.VC.db-shmvc17/.vs/otclient/v18/Insiders/Browse.VC.db-walvc17/otclient.vcxproj.uservc23/debug.propsvc23/otclient.slnvc23/otclient.vcxprojvc23/otclient.vcxproj.filtersvc23/release.propsvc23/settings.props
💤 Files with no reviewable changes (4)
- src/framework/sound/streamsoundsource.cpp
- vc17/.vs/otclient/v18/DocumentLayout.backup.json
- vc17/.vs/otclient/v18/DocumentLayout.json
- vc17/otclient.vcxproj.user
| set(WARNS_FLAGS "-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-unused-result") | ||
| if(WASM) | ||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNS_FLAGS} ${ARCH_FLAGS} -s USE_ZLIB=1 -s USE_LIBPNG=1 -s USE_SDL=2 -s USE_BOOST_HEADERS=1 -s USE_PTHREADS=1 -O1") # add -Ofast | ||
| set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNS_FLAGS} ${ARCH_FLAGS} -s USE_ZLIB=1 -s USE_LIBPNG=1 -s USE_SDL=2 -s USE_PTHREADS=1 -O1") # add -Ofast |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -e
printf 'Asio includes no código:\n'
rg -n '`#include` <asio' src
printf '\nWiring do build para Asio/Boost/WASM:\n'
rg -n 'USE_BOOST_HEADERS|find_package\(asio|asio::asio|WASM' src/framework/CMakeLists.txt
printf '\nAsio vendorizado no repositório (se não houver hits, o WASM depende de wiring externo):\n'
fd -HI -i 'asio.hpp|asio' .Repository: Mateuzkl/AstraClient
Length of output: 894
WASM não tem wiring explícito para headers do Asio (falha provável ao compilar)
src/framework/pch.hdefineASIO_STANDALONEe inclui<asio.hpp>e<asio/ssl.hpp>.- Em
src/framework/CMakeLists.txt, ofind_package(asio CONFIG REQUIRED)só é executado no ramoif(NOT WASM), enquanto o ramoif(WASM)(ex.:set(CMAKE_CXX_FLAGS ... -O1)na linha 176) não adiciona-s USE_BOOST_HEADERS=1nem inclui diretórios/caminhos para headers do Asio. - Sem um include path alternativo, o primeiro TU que incluir
pch.hpode falhar no preprocessamento. Ajustar o ramo WASM para fornecer os headers do Asio (ou trocar paraboost/asiose a intenção for usarUSE_BOOST_HEADERS).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/framework/CMakeLists.txt` at line 176, O ramo WASM em
src/framework/CMakeLists.txt não fornece os headers do Asio usados por
src/framework/pch.h (que define ASIO_STANDALONE e inclui
<asio.hpp>/<asio/ssl.hpp>), causando falha no preprocessamento; corrija o bloco
if(WASM) para expor os headers do Asio — ou habilite o uso dos headers Boost e
ajuste includes — adicionando a mesma configuração de include/directories usada
quando find_package(asio CONFIG REQUIRED) roda (ou alternadamente definir -s
USE_BOOST_HEADERS=1 e apontar para os include paths de boost/asio), garantindo
que pch.h encontre <asio.hpp> durante a compilação.
| m_context = std::make_shared< asio::ssl::context >(asio::ssl::context::tlsv12_client); | ||
| m_ssl = std::make_shared<asio::ssl::stream<asio::ip::tcp::socket&>>(m_socket, *m_context); | ||
| m_ssl->set_verify_mode(asio::ssl::verify_peer); | ||
| m_ssl->set_verify_callback([](bool, asio::ssl::verify_context&) { return true; }); | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Mostrar o contexto exato ao redor das linhas mencionadas
sed -n '1,140p' src/framework/http/session.cpp | nl -ba | sed -n '70,120p'
# 2) Verificar se existe outra configuração TLS no arquivo (verificações/callbacks/paths)
rg -n "set_verify_mode|set_verify_callback|host_name_verification|set_default_verify_paths|verify_peer|verify_none|verify_context" src/framework/http/session.cpp
# 3) Verificar de onde vem m_domain (ou equivalentes) e se há normalização/uso em outras partes
rg -n "m_domain|domain|host_name" src/framework/http/session.cppRepository: Mateuzkl/AstraClient
Length of output: 107
🌐 Web query:
Asio (boost::asio) ssl::host_name_verification usage set_verify_callback verify_context return true when permissive callback implications MITM
💡 Result:
In Boost.Asio, the ssl::verify_callback function is invoked by the underlying OpenSSL implementation to determine whether a peer certificate should be accepted [1][2]. The callback function signature is: bool verify_callback(bool preverified, boost::asio::ssl::verify_context& ctx); The preverified parameter indicates whether the certificate chain passed preliminary verification (e.g., signature checks and trust in the CA) [2]. If you write a custom callback that returns true regardless of the value of preverified (or specifically ignores preverified == false), you effectively bypass OpenSSL's validation mechanisms [2]. This makes your application vulnerable to Man-in-the-Middle (MITM) attacks, as it will accept invalid, expired, self-signed, or untrusted certificates [2][3]. To correctly handle verification: 1. Use boost::asio::ssl::host_name_verification when you need to verify the server's identity against its hostname according to RFC 6125 [4][5]. This is the recommended practice for most HTTPS-like scenarios [5]. 2. If you must implement a custom callback, you should return preverified as the baseline [2][6]. If you need additional checks, return preverified && [your_additional_checks] [2]. 3. Ensure that ssl::verify_peer mode is set on the stream, otherwise the callback may not even be invoked for certificate errors [5]. A permissive callback that always returns true is insecure and should never be used in production environments [2].
Citations:
- 1: https://www.boost.org/doc/libs/latest/doc/html/boost_asio/reference/ssl__context/set_verify_callback/overload1.html
- 2: https://stackoverflow.com/questions/19074104/boost-asio-https-and-host-certificate-verifcation
- 3: https://stackoverflow.com/questions/35175073/boost-ssl-verifies-expired-and-self-signed-certificates
- 4: https://www.boost.org/doc/libs/latest/doc/html/boost_asio/reference/ssl__host_name_verification.html
- 5: https://www.boost.org/doc/libs/latest/doc/html/boost_asio/overview/ssl.html
- 6: https://boost.org.cpp.al/doc/libs/1_84_0/doc/html/boost_asio/example/cpp11/ssl/client.cpp
Corrigir validação TLS: callback de verificação não pode aceitar tudo
O set_verify_callback([](bool, asio::ssl::verify_context&) { return true; }) torna a validação TLS efetivamente permissiva, ignorando o resultado preliminar e aceitando certificados/hostnames inválidos, o que viabiliza MITM mesmo com set_verify_mode(asio::ssl::verify_peer).
💡 Ajuste sugerido
m_context = std::make_shared< asio::ssl::context >(asio::ssl::context::tlsv12_client);
+ m_context->set_default_verify_paths();
m_ssl = std::make_shared<asio::ssl::stream<asio::ip::tcp::socket&>>(m_socket, *m_context);
m_ssl->set_verify_mode(asio::ssl::verify_peer);
- m_ssl->set_verify_callback([](bool, asio::ssl::verify_context&) { return true; });
+ m_ssl->set_verify_callback(asio::ssl::host_name_verification(m_domain));🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/framework/http/session.cpp` around lines 91 - 95, The current verify
callback on m_ssl (m_ssl->set_verify_callback(...)) unconditionally returns true
and disables TLS verification; replace this with proper verification by removing
the permissive lambda and using the platform verifier (keep
m_ssl->set_verify_mode(asio::ssl::verify_peer)) plus either call
m_ssl->set_verify_callback(asio::ssl::rfc2818_verification(hostname)) with the
server hostname, or implement a callback that returns (preverified &&
host-name-check) where you inspect the X509 certificate (e.g., using
X509_check_host or equivalent) to ensure the certificate matches the expected
hostname; update the code paths that construct m_ssl to accept/propagate the
server hostname so rfc2818_verification or host checks can be used.
| std::string location = m_headers["Location"]; | ||
| if (location.empty()) { | ||
| location = m_headers["location"]; | ||
| } |
There was a problem hiding this comment.
Normalize os headers ao parsear a resposta.
m_headers preserva o case original, mas o redirect só procura "Location"/"location" e o parser só marca chunked quando o valor é exatamente "chunked". Em HTTP, nomes de fields e nomes de transfer-coding são case-insensitive; respostas válidas com casing diferente vão perder redirect ou decodificar o corpo errado. (rfc-editor.org)
Also applies to: 191-213
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/framework/http/session.cpp` around lines 152 - 155, Normalize header
names and transfer-coding comparisons to be case-insensitive: when populating or
using m_headers (the parsed header map), convert header names to a canonical
form (e.g., lowercase) so lookups like the Location extraction (currently
checking "Location" and "location") work reliably, and when checking
transfer-encoding/transfer-coding values (the parser that marks chunked when
value == "chunked") compare lowercased values or otherwise perform
case-insensitive comparison; update the header-parsing code that fills m_headers
and the places that read Location and Transfer-Encoding/Transfer-Coding to use
the canonical/lowercased keys and lowercased value comparisons (affecting the
Location lookup and the chunked-detection logic).
| m_timer.expires_after(std::chrono::seconds(m_timeout)); | ||
|
|
||
| auto self(shared_from_this()); | ||
| if (m_ssl) { | ||
| boost::beast::http::async_read_some(*m_ssl, m_streambuf, m_response, | ||
| std::bind(&HttpSession::on_read, shared_from_this(), | ||
| std::placeholders::_1, std::placeholders::_2)); | ||
| m_ssl->async_read_some(m_streambuf.prepare(16384), | ||
| [this, self](const asio::error_code& ec, size_t bytes) { | ||
| m_streambuf.commit(bytes); | ||
| on_read_body(ec, bytes); | ||
| }); | ||
| } else { | ||
| boost::beast::http::async_read_some(m_socket, m_streambuf, m_response, | ||
| std::bind(&HttpSession::on_read, shared_from_this(), | ||
| std::placeholders::_1, std::placeholders::_2)); | ||
| m_socket.async_read_some(m_streambuf.prepare(16384), | ||
| [this, self](const asio::error_code& ec, size_t bytes) { | ||
| m_streambuf.commit(bytes); | ||
| on_read_body(ec, bytes); | ||
| }); | ||
| } |
There was a problem hiding this comment.
O timeout deixa de existir depois do primeiro chunk.
expires_after() cancela o async_wait() pendente. Como este ramo não registra outro async_wait, a transferência pode ficar presa indefinidamente após qualquer progresso parcial. (think-async.com)
💡 Ajuste sugerido
m_timer.expires_after(std::chrono::seconds(m_timeout));
+ m_timer.async_wait(std::bind(&HttpSession::onTimeout, shared_from_this(), std::placeholders::_1));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| m_timer.expires_after(std::chrono::seconds(m_timeout)); | |
| auto self(shared_from_this()); | |
| if (m_ssl) { | |
| boost::beast::http::async_read_some(*m_ssl, m_streambuf, m_response, | |
| std::bind(&HttpSession::on_read, shared_from_this(), | |
| std::placeholders::_1, std::placeholders::_2)); | |
| m_ssl->async_read_some(m_streambuf.prepare(16384), | |
| [this, self](const asio::error_code& ec, size_t bytes) { | |
| m_streambuf.commit(bytes); | |
| on_read_body(ec, bytes); | |
| }); | |
| } else { | |
| boost::beast::http::async_read_some(m_socket, m_streambuf, m_response, | |
| std::bind(&HttpSession::on_read, shared_from_this(), | |
| std::placeholders::_1, std::placeholders::_2)); | |
| m_socket.async_read_some(m_streambuf.prepare(16384), | |
| [this, self](const asio::error_code& ec, size_t bytes) { | |
| m_streambuf.commit(bytes); | |
| on_read_body(ec, bytes); | |
| }); | |
| } | |
| m_timer.expires_after(std::chrono::seconds(m_timeout)); | |
| m_timer.async_wait(std::bind(&HttpSession::onTimeout, shared_from_this(), std::placeholders::_1)); | |
| auto self(shared_from_this()); | |
| if (m_ssl) { | |
| m_ssl->async_read_some(m_streambuf.prepare(16384), | |
| [this, self](const asio::error_code& ec, size_t bytes) { | |
| m_streambuf.commit(bytes); | |
| on_read_body(ec, bytes); | |
| }); | |
| } else { | |
| m_socket.async_read_some(m_streambuf.prepare(16384), | |
| [this, self](const asio::error_code& ec, size_t bytes) { | |
| m_streambuf.commit(bytes); | |
| on_read_body(ec, bytes); | |
| }); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/framework/http/session.cpp` around lines 316 - 331, The timeout is lost
after the first chunk because calling m_timer.expires_after(...) cancels any
pending async_wait; you must re-arm the wait after resetting the timer. Update
the read logic (around m_timer, m_timer.expires_after, and the async_read_some
callers in the session code that invoke on_read_body) so each new
expires_after(...) is followed by a matching m_timer.async_wait(...)
registration (or centralize into a start_read_with_timeout helper that calls
m_timer.expires_after(...) then m_timer.async_wait(...) and then the appropriate
async_read_some on m_ssl or m_socket), ensuring the timer's handler will cancel
the socket/stream on timeout and that the async_wait is re-registered for every
subsequent chunk.
| void on_resolve(const asio::error_code& ec, asio::ip::tcp::resolver::iterator iterator); | ||
| void on_connect(const asio::error_code& ec); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Localizar o arquivo e ler o trecho das linhas citadas
ls -la src/framework/http || true
nl -ba src/framework/http/session.h | sed -n '1,120p'
# 2) Buscar por declarações/definições de on_resolve/on_connect e uso de async_resolve/async_connect
rg -n "on_resolve\s*\(|on_connect\s*\(|async_resolve\s*\(|async_connect\s*\(" src/framework/http -S
# 3) Tentar localizar a implementação em .cpp/.cc/.ipp/.inl correlatos
# (sem assumir caminho exato: buscar pelo nome das funções no repo)
rg -n "void\s+.*on_resolve\s*\(" -S .
# 4) Inspecionar o corpo do on_resolve (se encontrado) e o uso do resultado/iterator
# Pegando os contextos ao redor das match lines
matches=$(rg -n "on_resolve\s*\(" -S . || true)
echo "$matches" | head -n 50
# 5) Ler ao redor dos usos encontrados
for f in $(echo "$matches" | awk -F: '{print $1}' | sort -u); do
echo "---- $f (relevante) ----"
# mostra alguns contextos perto do primeiro match
ln=$(echo "$matches" | awk -F: -v file="$f" '$1==file{print $2; exit}')
if [[ -n "${ln:-}" ]]; then
start=$((ln-30)); end=$((ln+80));
if (( start<1 )); then start=1; fi
nl -ba "$f" | sed -n "${start},${end}p"
else
nl -ba "$f" | head -n 160
fi
doneRepository: Mateuzkl/AstraClient
Length of output: 671
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Listar diretório
ls -la src/framework/http
# 2) Mostrar session.h com line numbers via awk
awk '{printf "%6d\t%s\n", NR, $0}' src/framework/http/session.h | sed -n '1,140p'
# 3) Buscar usos relevantes em session.h/cpp
rg -n "on_resolve\s*\(|async_resolve\s*\(|async_connect\s*\(" src/framework/http/session.h src/framework/http/session.cpp -S || true
# 4) Mostrar definição/implementação de on_resolve em session.cpp (se existir)
rg -n "on_resolve\s*\(" src/framework/http/session.cpp -S || true
# 5) Mostrar um trecho maior de session.cpp para capturar o contrato completo
awk '{printf "%6d\t%s\n", NR, $0}' src/framework/http/session.cpp | sed -n '1,240p'Repository: Mateuzkl/AstraClient
Length of output: 14756
🌐 Web query:
Asio standalone ip::tcp::resolver::async_resolve(host, service, handler) handler signature iterator results_type
💡 Result:
In Asio (both the Boost and standalone versions), the completion handler for ip::tcp::resolver::async_resolve must have the following signature [1][2][3]: void handler( const boost::system::error_code& error, boost::asio::ip::tcp::resolver::results_type results); The completion signature is defined as void(boost::system::error_code, results_type) [1][3]. The results_type (boost::asio::ip::tcp::resolver::results_type) is a typedef for boost::asio::ip::basic_resolver_resultsboost::asio::ip::tcp [4][5]. It represents a range over the resolved endpoints and provides iterator access to the individual resolution entries [4][5]. A successful resolution operation is guaranteed to pass a non-empty range to the handler [1][3].
Citations:
- 1: https://www.boost.org/doc/libs/latest/doc/html/boost_asio/reference/ip__basic_resolver/async_resolve/overload1.html
- 2: https://www.boost.org/doc/libs/1_87_0/boost/asio/ip/basic_resolver.hpp
- 3: https://www.boost.org/doc/libs/1_79_0/doc/html/boost_asio/reference/ip__basic_resolver/async_resolve/overload1.html
- 4: https://www.boost.org/doc/libs/latest/doc/html/boost_asio/reference/ip__basic_resolver/results_type.html
- 5: https://www.boost.org/doc/libs/1_90_0/doc/html/boost_asio/reference/ip__basic_resolver/results_type.html
Corrigir o tipo do callback de on_resolve (iterator vs results_type)
A assinatura atual de HttpSession::on_resolve usa asio::ip::tcp::resolver::iterator, mas o m_resolver.async_resolve(m_domain, std::to_string(m_port), ...) (overload com 3 argumentos) completa o handler com asio::ip::tcp::resolver::results_type. Isso gera quebra na compilação e impede conectar varrendo todos os endpoints resolvidos.
💡 Ajuste sugerido
- void on_resolve(const asio::error_code& ec, asio::ip::tcp::resolver::iterator iterator);
+ void on_resolve(const asio::error_code& ec, asio::ip::tcp::resolver::results_type results);No .cpp, troque o uso atual de m_socket.async_connect(*iterator, ...) por asio::async_connect(m_socket, results, ...) (e remova/ajuste o iterator->endpoint().port(m_port) já que você está passando service/porta em async_resolve).
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| void on_resolve(const asio::error_code& ec, asio::ip::tcp::resolver::iterator iterator); | |
| void on_connect(const asio::error_code& ec); | |
| void on_resolve(const asio::error_code& ec, asio::ip::tcp::resolver::results_type results); | |
| void on_connect(const asio::error_code& ec); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/framework/http/session.h` around lines 63 - 64, A assinatura de
HttpSession::on_resolve está errada: o handler de
m_resolver.async_resolve(m_domain, std::to_string(m_port), ...) recebe
asio::ip::tcp::resolver::results_type, não resolver::iterator, então altere
HttpSession::on_resolve para aceitar const
asio::ip::tcp::resolver::results_type& results (ou results_type) e adapte o
corpo correspondente; no .cpp, substitua a lógica que usava
m_socket.async_connect(*iterator, ...) por asio::async_connect(m_socket,
results, /* bind your existing connect handler */) e remova/pare de ajustar
iterator->endpoint().port(m_port) já que a porta/serviço foi passada ao
async_resolve; mantenha nomes existentes (m_resolver, m_socket, on_resolve,
on_connect) ao aplicar a correção.
| auto self(shared_from_this()); | ||
| boost::asio::post(m_io, [&, self] { | ||
| asio::post(m_io, [&, self] { | ||
| g_proxies.erase(self); | ||
| disconnect(); | ||
| boost::system::error_code ec; | ||
| asio::error_code ec; | ||
| m_timer.cancel(ec); | ||
| }); |
There was a problem hiding this comment.
Cancele operações pendentes ao encerrar o proxy.
terminate() só fecha o socket e cancela o timer. Se um async_resolve ou async_connect já estiver em voo, os callbacks aqui ainda podem completar depois de m_terminated = true e recolocar o proxy em estado conectado, reabrindo tráfego após a remoção de g_proxies.
💡 Ajuste sugerido
void Proxy::terminate()
{
if (m_terminated)
return;
m_terminated = true;
@@
auto self(shared_from_this());
asio::post(m_io, [&, self] {
g_proxies.erase(self);
+ asio::error_code resolverEc;
+ m_resolver.cancel(resolverEc);
disconnect();
asio::error_code ec;
m_timer.cancel(ec);
});
}
@@
m_resolver.async_resolve(m_host, "http", [self](const asio::error_code& ec,
asio::ip::tcp::resolver::results_type results) {
+ if (self->m_terminated)
+ return;
auto endpoint = asio::ip::tcp::endpoint();
@@
self->m_socket = asio::ip::tcp::socket(self->m_io);
self->m_lastPingSent = std::chrono::high_resolution_clock::now(); // used for async_connect timeout
self->m_socket.async_connect(endpoint, [self, endpoint](const asio::error_code& ec) {
+ if (self->m_terminated)
+ return;
if (ec) {
self->m_state = STATE_NOT_CONNECTED;
return;
}Also applies to: 94-136
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/framework/proxy/proxy_client.cpp` around lines 35 - 41, terminate()
currently only closes the socket and cancels the timer but leaves in-flight
async operations (e.g., async_resolve, async_connect) able to complete and
re-mark the proxy connected; update terminate() and related callback code
(callbacks started in the async_resolve/async_connect flow) to: set m_terminated
= true, cancel any pending resolver and socket operations (call cancel() on the
resolver and shutdown/close the socket with error handling), ensure callbacks
check m_terminated before mutating state or re-adding to g_proxies, and use
weak_ptr/owned self pattern in those callbacks to avoid resurrecting the object
after termination; apply the same fixes to the other similar block(s) referenced
around the 94-136 region so all pending async operations are cancelled and
guarded by m_terminated checks.
| ip = asio::detail::socket_ops::network_to_host_long(ip); | ||
| asio::ip::address_v4 address_v4 = asio::ip::address_v4(ip); | ||
| return address_v4.to_string(); | ||
| } | ||
|
|
||
| uint32 string_to_ip(const std::string& string) | ||
| { | ||
| boost::asio::ip::address_v4 address_v4 = boost::asio::ip::address_v4::from_string(string); | ||
| return boost::asio::detail::socket_ops::host_to_network_long(address_v4.to_ulong()); | ||
| asio::ip::address_v4 address_v4 = asio::ip::make_address_v4(string); | ||
| return asio::detail::socket_ops::host_to_network_long(address_v4.to_uint()); |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Is asio::detail::socket_ops::host_to_network_long/network_to_host_long part of Asio's public stable API, and what public alternative is recommended for byte-order conversion in standalone Asio?
💡 Result:
The functions asio::detail::socket_ops::host_to_network_long and network_to_host_long are not part of Asio's public, stable API [1][2]. As indicated by their placement within the detail namespace, they are internal implementation details used by Asio and are subject to change or removal without notice [1][3][2]. You should not rely on them in your own code [3]. For standalone Asio, or when using Asio with Boost, the recommended alternatives for byte-order conversion are: 1. Standard POSIX/Socket functions: You can use the standard C socket API functions, which are widely available on most platforms: ntohl, htonl, ntohs, and htons (typically found in <arpa/inet.h> on POSIX or <winsock2.h> on Windows) [4]. 2. Boost.Endian library: If you are using Asio in a Boost-enabled project, the Boost.Endian library is the preferred, robust way to handle byte-order conversions [5][4]. It provides clean, type-safe interfaces, including endian-specific integer types (e.g., boost::endian::big_int32_t, boost::endian::little_int32_t) and conversion functions [6][7][8][5]. 3. C++23 standard library: If your environment supports C++23, you can use the <bit> header, which provides std::byteswap for byte reversal, which is the foundational operation needed to implement endianness conversions manually if a full library is not desired.
Citations:
- 1: https://github.com/boostorg/asio/blob/62864c57/include/boost/asio/detail/socket_ops.hpp
- 2: https://ver.miun.se/3DLabDocs/socket__ops_8hpp_source.html
- 3: https://live.boost.org/doc/libs/1_88_0/boost/asio/ip/detail/socket_option.hpp
- 4: https://stackoverflow.com/questions/49033780/sequential-communication-failed-with-boostasiostreambuf-in-binary-way
- 5: https://stackoverflow.com/questions/72849733/boost-asio-with-little-endian
- 6: https://www.boost.org/doc/libs/1_77_0/libs/endian/doc/html/endian.html
- 7: https://beta.boost.org/doc/libs/1_79_0/libs/endian/doc/html/endian.html
- 8: https://www.boost.org/libs/endian
Evite asio::detail::socket_ops para conversão de endianness
asio::detail::socket_ops::host_to_network_long/network_to_host_long ficam no namespace detail, ou seja, não fazem parte de API pública/estável; isso pode quebrar com atualizações e afetar a superfície exposta para Lua via ip_to_string, string_to_ip e listSubnetAddresses em src/framework/luafunctions.cpp (usando os helpers de src/framework/stdext/net.cpp:30-38). Prefira conversão via htonl/ntohl (ou htons/ntohs se aplicável) e/ou um helper local de endianness em stdext (alternativa: boost::endian se estiver no ecossistema Boost).
Also applies to: 47-47
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/framework/stdext/net.cpp` around lines 30 - 38, The code uses
asio::detail::socket_ops::network_to_host_long and host_to_network_long in
ip_to_string and string_to_ip (affecting listSubnetAddresses) which relies on
non-public APIs; replace those calls with standard endianness conversions such
as ntohl/htonl (or a local stdext endian helper / boost::endian equivalent) so
endianness conversion no longer depends on asio::detail. Update ip_to_string to
call ntohl on the IPv4 uint32 before constructing asio::ip::address_v4, and
update string_to_ip to call htonl on address_v4.to_uint() before returning;
ensure any other occurrences (e.g., listSubnetAddresses) are changed the same
way.
| stdext::tolower(aligment); | ||
| aligment.erase(std::remove(aligment.begin(), aligment.end(), ' '), aligment.end()); |
There was a problem hiding this comment.
Normalize toda a whitespace antes do mapeamento.
Aqui só o caractere ' ' é removido. Entradas com \t, \r ou \n continuam no token e passam a cair em AlignNone/AnchorNone, enquanto translateState e translateAutoFocusPolicy já tratam esse caso com stdext::trim.
💡 Ajuste sugerido
Fw::AlignmentFlag Fw::translateAlignment(std::string aligment)
{
stdext::tolower(aligment);
+ stdext::trim(aligment);
aligment.erase(std::remove(aligment.begin(), aligment.end(), ' '), aligment.end());
if(aligment == "topleft")
return Fw::AlignTopLeft;
@@
Fw::AnchorEdge Fw::translateAnchorEdge(std::string anchorEdge)
{
stdext::tolower(anchorEdge);
+ stdext::trim(anchorEdge);
anchorEdge.erase(std::remove(anchorEdge.begin(), anchorEdge.end(), ' '), anchorEdge.end());
if(anchorEdge == "left")
return Fw::AnchorLeft;Also applies to: 54-55
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/framework/ui/uitranslator.cpp` around lines 29 - 30, A entrada em
'aligment' só remove espaços ' ' mas deixa tabs/newlines/carriage returns,
causando fallback para AlignNone/AnchorNone; antes do mapeamento aplique
normalização completa de whitespace (usar stdext::trim ou remover todos os
caracteres onde std::isspace(c) é true), então chame stdext::tolower(aligment) e
continue; refatore as ocorrências em que 'aligment' é processado (mesmo padrão
citado nas linhas 54-55) para usar a mesma normalização usada por translateState
e translateAutoFocusPolicy.
| std::size_t seed = 0; | ||
| for (uint8_t b : u) { | ||
| std::size_t to_hash = b; | ||
| seed ^= to_hash + 0x9e3779b9 + (seed << 6) + (seed >> 2); | ||
| } | ||
|
|
||
| std::string key; | ||
| key.assign((const char *)&hash, sizeof(hash)); | ||
| key.assign((const char *)&seed, sizeof(seed)); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
base="$(git merge-base HEAD origin/main 2>/dev/null || git rev-parse HEAD~1)"
echo "=== Diff do getCryptKey ==="
git diff --unified=40 "$base"...HEAD -- src/framework/util/crypt.cpp | sed -n '/std::string Crypt::getCryptKey/,/return key;/p'
echo
echo "=== Call sites relevantes ==="
rg -n -C2 '\b(getMachineUUID|setMachineUUID|encrypt\(|decrypt\()' srcRepository: Mateuzkl/AstraClient
Length of output: 3539
Evite serializar std::size_t como chave em Crypt::getCryptKey
Em src/framework/util/crypt.cpp (lin. 254-261), a chave é montada com key.assign((const char*)&seed, sizeof(seed)) onde seed é std::size_t; isso varia com sizeof(size_t) e endianness entre plataformas/builds, quebrando compatibilidade das mensagens criptografadas (e do decrypter).
Derive a chave em um tamanho fixo (ex.: uint64_t/16 bytes) e serialize em uma ordem de bytes definida antes de usar no xorCrypt.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/framework/util/crypt.cpp` around lines 254 - 261, In Crypt::getCryptKey
the code serializes a platform-dependent std::size_t seed into key via
key.assign((const char*)&seed,...), causing size/endian variability; instead
convert the computed seed into a fixed-size integer (e.g., uint64_t or a fixed
16-byte buffer derived from the seed), then explicitly serialize it to bytes in
a defined byte order (big-endian or little-endian using shifts/masks) and assign
those bytes to key before passing to xorCrypt; update references to seed in
getCryptKey to use the fixed-size value and ensure xorCrypt always receives the
same-length, order-deterministic key.
| <ConfigurationType>Application</ConfigurationType> | ||
| <UseDebugLibraries>false</UseDebugLibraries> | ||
| <PlatformToolset>v143</PlatformToolset> | ||
| <PlatformToolset>v145</PlatformToolset> |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Qual é o valor válido de <PlatformToolset> para a versão mais recente do Visual Studio/Build Tools e qual versão mínima oferece suporte a v145? Se v145não for um toolset amplamente disponível, qual é o valor correto suportado para projetos.vcxproj com C++23?
💡 Result:
O valor válido e mais recente de PlatformToolset para o Visual Studio 2026 é v145 [1][2][3]. Sobre o suporte ao v145: Este toolset foi introduzido especificamente com o Visual Studio 2026 (versão 18.0) [1][2]. Não é um toolset legado disponível em versões anteriores do Visual Studio, mas sim o sucessor direto do v143 (utilizado no Visual Studio 2022) [3]. Portanto, a versão mínima do Visual Studio que oferece suporte ao v145 é o Visual Studio 2026 [1][2]. Sobre C++23 e.vcxproj: O valor v145 é o valor correto e suportado para projetos.vcxproj que visam utilizar funcionalidades de C++23 no Visual Studio 2026 [1]. Para habilitar o suporte ao padrão C++23, além de definir o PlatformToolset como v145, você deve configurar a propriedade de idioma para /std:c++23preview ou, para as funcionalidades mais recentes, utilizar /std:c++latest nas configurações do seu projeto [1][4]. Resumo: - Toolset atual: v145 [1][3]. - Suporte mínimo: Visual Studio 2026 [1][2]. - Para C++23: Utilize v145 em conjunto com a flag /std:c++23preview ou /std:c++latest [1].
Citations:
- 1: https://learn.microsoft.com/en-us/cpp/overview/what-s-new-for-msvc?view=msvc-170
- 2: https://devblogs.microsoft.com/cppblog/upgrading-c-projects-to-visual-studio-2026/
- 3: https://github.com/KirillOsenkov/MSBuildTools/blob/main/msvc_toolset_cheatsheet.md
- 4: https://github.com/MicrosoftDocs/cpp-docs/blob/main/docs/build/reference/general-property-page-project.md
🌐 Web query:
PlatformToolset v145 Visual Studio 2026 msbuild property documentation
💡 Result:
The PlatformToolset v145 is the default C++ toolset for Visual Studio 2026 (version 18.0) [1][2][3]. The PlatformToolset is an MSBuild property that determines which Microsoft C++ (MSVC) toolset—including the compiler (cl.exe), linker (link.exe), and standard libraries—is used to build a C++ project [4][5][6]. Setting this property allows you to target specific versions of the MSVC build tools regardless of the host Visual Studio version installed, provided the chosen toolset is installed on the machine [4][3]. Key characteristics of the v145 toolset include: - Visual Studio Version: Introduced with Visual Studio 2026 (18.0) [1][2][3]. - MSVC Build Tools Version: Corresponds to version 14.50 [1][2][3]. - Project File Usage: In.vcxproj files, the property is defined within a PropertyGroup, typically labeled "Globals" [7]: v145 - Command Line Usage: You can override the toolset during an MSBuild invocation using the command-line switch [4]: msbuild myProject.vcxproj /p:PlatformToolset=v145 The v145 toolset continues the established naming convention and maintains binary compatibility with previous versions (v140, v141, v142, and v143), allowing for interoperability between code built with these different toolsets [5][3][6]. It is recommended to use the Property Manager in Visual Studio to retarget projects to the latest toolset or to manually edit the.vcxproj file if managing builds outside the IDE [2][5][8].
Citations:
- 1: https://learn.microsoft.com/en-us/cpp/overview/what-s-new-for-msvc?view=msvc-170
- 2: https://devblogs.microsoft.com/cppblog/upgrading-c-projects-to-visual-studio-2026/
- 3: https://github.com/KirillOsenkov/MSBuildTools/blob/main/msvc_toolset_cheatsheet.md
- 4: https://learn.microsoft.com/en-us/cpp/build/reference/msbuild-visual-cpp-overview?view=msvc-170
- 5: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/build/how-to-modify-the-target-framework-and-platform-toolset.md
- 6: https://stackoverflow.com/questions/27517662/what-is-platform-toolset-setting-in-visual-studio-project
- 7: brettcannon/cpython@c06f4f4
- 8: https://learn.microsoft.com/en-us/cpp/build/project-property-inheritance?view=msvc-170
Ajustar CI/documentação para garantir o availability do PlatformToolset v145
O PlatformToolset v145 foi introduzido no Visual Studio 2026 (MSVC 14.50) e só funciona quando o toolset v145 está instalado; com VS/Build Tools mais antigos, o MSBuild falha antes mesmo de compilar. Como vc23/otclient.vcxproj já fixa PlatformToolset=v145 (linhas 42, 51, 60, 78 e 87), alinhar a pipeline e requisitos mínimos para instalar o VS 2026 Build Tools (ou definir um toolset alternativo suportado).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@vc23/otclient.vcxproj` at line 42, O ficheiro vc23/otclient.vcxproj define
PlatformToolset como v145 em várias entradas; atualiza a documentação e a
pipeline para garantir que o Visual Studio 2026 / Build Tools com MSVC toolset
v145 é instalado antes do MSBuild, ou altere as entradas PlatformToolset (ex.:
as tags PlatformToolset que contêm "v145") para um toolset alternativo suportado
pela CI (por exemplo v142) e documenta o requisito mínimo de build na README/CI
config para evitar falhas de MSBuild.


Summary by CodeRabbit
Release Notes
Bug Fixes
Improvements