FrozenK 0 Posted December 20, 2024 (edited) Hello, I'm trying to configure the most simple websocket client (with TSslWebSocketCli) and server (with TSslHttpAppSrv) in order to get them communicate with each other locally. Worth noting that I'm a beginner in the internet communication protocol world, this is why I'm trying to get the minimum working and then I will build from that. I'm using the ICS 9.0 C++ package, I believe I have a configuration problem more than a C++ problem. For the client part, I configured the following (no TLS for now) : client->SocketFamily = sfAnyIPv4; client->DebugLevel = DebugHdr; client->CertVerMethod = CertVerNone; client->SslCliSecurity = sslCliSecDefault; client->URL = "ws://127.0.0.1/"; client->WSPingSecs = 10; event handlers to get something printed in the terminal : client->OnHttpRestProg = HttpRestProg; client->OnWSFrameRcvd = FrameRcvd; client->OnWSConnected = Connected; client->OnWSDisconnected = Disconnected; For the server part, based on the Delphi samples OverbyteIcsBasicWebServer1.pas and OverbyteIcsSslMultiWebServ.pas, I configured : server->AuthRealm = "ics"; server->SocketErrs = wsErrFriendly; server->ExclusiveAddr = true; server->SessionTimeout = 300; server->MaxSessions = 100; server->OnDisplay = Display; server->SslEnable = false; server->SslCliCertMethod = sslCliCertNone; server->SslCertAutoOrder = false; server->CertExpireDays = 30; server->OcspSrvStapling = false; server->AddGetAllowedPath("/", afBeginBy, "WEB-APP"); server->OnClientConnect = ClientConnect; I added an host : server->IcsHosts->Clear(); TIcsHost *host = new TIcsHost(server->IcsHosts); host->HostEnabled = true; host->HostNames->Text = "localhost"; host->HostTag = "WEB-APP"; host->Descr = "WebApp Server"; host->BindIpAddr = "127.0.0.1"; host->BindNonPort = 80; host->BindSslPort = 0; host->WebDefDoc = "index.html"; host->WebDocDir = dir + "data"; When the client is connecting (TSslWebSocketCli.WSConnect), OnClientConnect is triggered server side, then : THttpWSSrvConn *conn = (THttpWSSrvConn *)Client; conn->WSessionCookie = "OverbyteIcsWebAppServer" + server->Port; conn->OnWSLogEvent = ClientLogEvent; conn->OnWSHandshake = ClientHandShake; conn->OnWSDisconnected = ClientDisconnected; conn->OnWSFrameRcvd = ClientFrameRcvd; conn->OnWSFrameSent = ClientFrameSent; conn->OnWSReady = ClientReady; conn->OnWSPingTimer = ClientPingTimer; conn->OnBgException = ClientBgException; Then the server handle the request (these are called : THttpConnection::ProcessRequest(), ::ProcessGet(), ::ProcessGetHeadDel(), ::SendDocument()...) and returns an "HTTP/1.1 200 OK" response to the client. From TSslWebSocketCli.WSConnect I get "WebSocket: Failed to Connect:" but the LastResponse string is empty. It looks like the server treats my websocket upgrade request as a "classic" request, so it returns an "HTTP/1.1 200 OK" response instead of the expected "HTTP/1.1 101 Switching Protocols". To make sure my client part was ok, I quickly tried it on a node.js websocket server, no problem, I get the "101 Switching Protocols" response and the websocket connection is established. If I do not use TSslWebSocketCli.WSConnect but do a "manual" GET with an upgrade request header and on server side add an url handler (TUrlHandlerIndexHtml) and send a response header through AnswerStream, the connection is established. But if I send frames from the client, OnWSFrameRcvd is not triggred server side (as expected I believe since server has no clue I handled the upgrade "myself"). Hopefully this post makes sense, in short, I don't understand why my upgrade request on url: "ws://127.0.0.1/" fails on the ICS server, any help would be appreciated. Thanks in advance. Edited December 20, 2024 by FrozenK Share this post Link to post
Angus Robertson 590 Posted December 20, 2024 I'd first make the general comment that it is always best to develop and test the two parts of client/server applications separately, against known working versions. In this case, with the ICS OverbyteIcsSslMultiWebServ and OverbyteIcsHttpRestTst samples. Don't know if C++ allows you to build them, but the wiki site allows you to download prebuilt executable files. Your settings are missing a websocket path or page, just ws://127.0.0.1/ so you are assuming the web server default HTML page is actually a Websocket request, this was never testing with the ICS web server, perhaps my fault for not expecting anyone to try that. Since you set default page to index.html, I assume that is the websocket URL you are checking for, but you don;t show any of that code. I find it best to use a virtual path /websocket/ to clarify that such requests from HTML. Angus Share this post Link to post
FrozenK 0 Posted December 26, 2024 Thanks a lot for your help Angus. After I modified the path and also specified "THttpWSSrvConn" as the "server->ClientClass" (whichi I missed), it is now working fine. Happy Holiday season. Share this post Link to post