-
Notifications
You must be signed in to change notification settings - Fork 302
Description
Hi @chronoxor,
Really liking the design of CppServer
!....however, unfortunately, I am running into issues attempting to connect to a wss:// endpoint.
In general, I am unable to get a simple example of connecting working so any help explaining how to correctly resolve and connect to a websocket endpoint specified by a wss:// uri would be greatly appreciated!
For example to connect to wss://ws.okx.com:8443/ws/v5/public
(taken from here) I attempted the following based on the wss client example:
// ...int main() {
// Create a new Asio service
auto service = std::make_shared<AsioService>();
service->Start();
// Create and prepare a new SSL client context
auto context = std::make_shared<CppServer::Asio::SSLContext>(asio::ssl::context::tlsv12);
context->set_default_verify_paths();
context->set_root_certs();
context->set_verify_mode(asio::ssl::verify_peer | asio::ssl::verify_fail_if_no_peer_cert);
context->load_verify_file("../external/CppServer/tools/certificates/ca.pem");
// Use TCPResolver to lookup DNS
// See: https://github.com/chronoxor/CppServer/issues/55
auto resolver = std::make_shared<CppServer::Asio::TCPResolver>(service);
// @NOTE ClientWebsocket is a child class of `public CppServer::WS::WSSClient`
auto ws = std::make_shared<ClientWebsocket>(service, context, "ws.okx.com", 8443);
ws->Connect(resolver);
and the upgrade request attempt:
class ClientWebsocket : public CppServer::WS::WSSClient
{
public:
using CppServer::WS::WSSClient::WSSClient;
protected:
void onWSConnecting(CppServer::HTTP::HTTPRequest &request) override
{
request.SetBegin("GET", "/ws/v5/public", "HTTP/2");
request.SetHeader("Host", address() + ":8443"); // @todo
request.SetHeader("Upgrade", "websocket");
request.SetHeader("Connection", "upgrade");
request.SetHeader("Sec-WebSocket-Key", CppCommon::Encoding::Base64Encode(ws_nonce()));
request.SetHeader("Accept", "/");
// request.SetHeader("Sec-WebSocket-Version", "13");
request.SetHeader("User-Agent", "beast.v1");
}
This did not work, and my comments are:
(1) Do I need to set SNI somewhere on the stream native handle (using SSL_set_tlsext_host_name
)
(2) Why (once SNI is set) the upgrade request is not working? If you have any experience with this.
NOTE: something like this seemed to get round initial SSL v3 handshake errors
bool SSLClient::Connect(const std::shared_ptr<TCPResolver>& resolver) {
// ...
std::cout << "Setting SNI Hostname: " << _address << std::endl;
if(SSL_set_tlsext_host_name(_stream.native_handle(), _address.c_str())) {
std::cout << "Success!" << std::endl;
}
else {
std::cout << "Failed!" << std::endl;
}
// ...