618 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			618 lines
		
	
	
		
			27 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE html>
 | |
| <html lang="en">
 | |
|     <head>
 | |
|         <meta charset="utf-8">
 | |
|         <meta http-equiv="X-UA-Compatible" content="IE=edge">
 | |
|         <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | |
|         
 | |
|         
 | |
|         
 | |
|         <link rel="shortcut icon" href="../img/favicon.ico">
 | |
|         <title>Examples - IXWebSocket</title>
 | |
|         <link href="../css/bootstrap.min.css" rel="stylesheet">
 | |
|         <link href="../css/font-awesome.min.css" rel="stylesheet">
 | |
|         <link href="../css/base.css" rel="stylesheet">
 | |
|         <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css">
 | |
| 
 | |
|         <script src="../js/jquery-1.10.2.min.js" defer></script>
 | |
|         <script src="../js/bootstrap.min.js" defer></script>
 | |
|         <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
 | |
|         <script>hljs.initHighlightingOnLoad();</script> 
 | |
|     </head>
 | |
| 
 | |
|     <body>
 | |
|         <div class="navbar fixed-top navbar-expand-lg navbar-dark bg-primary">
 | |
|             <div class="container">
 | |
|                 <a class="navbar-brand" href="..">IXWebSocket</a>
 | |
|                 <!-- Expander button -->
 | |
|                 <button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbar-collapse">
 | |
|                     <span class="navbar-toggler-icon"></span>
 | |
|                 </button>
 | |
| 
 | |
|                 <!-- Expanded navigation -->
 | |
|                 <div id="navbar-collapse" class="navbar-collapse collapse">
 | |
|                         <!-- Main navigation -->
 | |
|                         <ul class="nav navbar-nav">
 | |
|                             <li class="navitem">
 | |
|                                 <a href=".." class="nav-link">Home</a>
 | |
|                             </li>
 | |
|                             <li class="navitem">
 | |
|                                 <a href="../CHANGELOG/" class="nav-link">Changelog</a>
 | |
|                             </li>
 | |
|                             <li class="navitem">
 | |
|                                 <a href="../build/" class="nav-link">Build</a>
 | |
|                             </li>
 | |
|                             <li class="navitem">
 | |
|                                 <a href="../cobra/" class="nav-link">Cobra</a>
 | |
|                             </li>
 | |
|                             <li class="navitem">
 | |
|                                 <a href="../design/" class="nav-link">Design</a>
 | |
|                             </li>
 | |
|                             <li class="navitem">
 | |
|                                 <a href="../packages/" class="nav-link">Packages</a>
 | |
|                             </li>
 | |
|                             <li class="navitem active">
 | |
|                                 <a href="./" class="nav-link">Examples</a>
 | |
|                             </li>
 | |
|                             <li class="navitem">
 | |
|                                 <a href="../ws/" class="nav-link">Ws</a>
 | |
|                             </li>
 | |
|                         </ul>
 | |
| 
 | |
|                     <ul class="nav navbar-nav ml-auto">
 | |
|                         <li class="nav-item">
 | |
|                             <a href="#" class="nav-link" data-toggle="modal" data-target="#mkdocs_search_modal">
 | |
|                                 <i class="fa fa-search"></i> Search
 | |
|                             </a>
 | |
|                         </li>
 | |
|                             <li class="nav-item">
 | |
|                                 <a rel="prev" href="../packages/" class="nav-link">
 | |
|                                     <i class="fa fa-arrow-left"></i> Previous
 | |
|                                 </a>
 | |
|                             </li>
 | |
|                             <li class="nav-item">
 | |
|                                 <a rel="next" href="../ws/" class="nav-link">
 | |
|                                     Next <i class="fa fa-arrow-right"></i>
 | |
|                                 </a>
 | |
|                             </li>
 | |
|                     </ul>
 | |
|                 </div>
 | |
|             </div>
 | |
|         </div>
 | |
| 
 | |
|         <div class="container">
 | |
|             <div class="row">
 | |
|                     <div class="col-md-3"><div class="navbar-light navbar-expand-md bs-sidebar hidden-print affix" role="complementary">
 | |
|     <div class="navbar-header">
 | |
|         <button type="button" class="navbar-toggler collapsed" data-toggle="collapse" data-target="#toc-collapse" title="Table of Contents">
 | |
|             <span class="fa fa-angle-down"></span>
 | |
|         </button>
 | |
|     </div>
 | |
| 
 | |
|     
 | |
|     <div id="toc-collapse" class="navbar-collapse collapse card bg-secondary">
 | |
|         <ul class="nav flex-column">
 | |
|             
 | |
|             <li class="nav-item" data-level="1"><a href="#examples" class="nav-link">Examples</a>
 | |
|               <ul class="nav flex-column">
 | |
|             <li class="nav-item" data-level="2"><a href="#windows-note" class="nav-link">Windows note</a>
 | |
|               <ul class="nav flex-column">
 | |
|               </ul>
 | |
|             </li>
 | |
|             <li class="nav-item" data-level="2"><a href="#websocket-client-api" class="nav-link">WebSocket client API</a>
 | |
|               <ul class="nav flex-column">
 | |
|               </ul>
 | |
|             </li>
 | |
|             <li class="nav-item" data-level="2"><a href="#websocket-server-api" class="nav-link">WebSocket server API</a>
 | |
|               <ul class="nav flex-column">
 | |
|               </ul>
 | |
|             </li>
 | |
|             <li class="nav-item" data-level="2"><a href="#http-client-api" class="nav-link">HTTP client API</a>
 | |
|               <ul class="nav flex-column">
 | |
|               </ul>
 | |
|             </li>
 | |
|             <li class="nav-item" data-level="2"><a href="#http-server-api" class="nav-link">HTTP server API</a>
 | |
|               <ul class="nav flex-column">
 | |
|               </ul>
 | |
|             </li>
 | |
|             <li class="nav-item" data-level="2"><a href="#tls-support-and-configuration" class="nav-link">TLS support and configuration</a>
 | |
|               <ul class="nav flex-column">
 | |
|               </ul>
 | |
|             </li>
 | |
|               </ul>
 | |
|             </li>
 | |
|         </ul>
 | |
|     </div>
 | |
| </div></div>
 | |
|                     <div class="col-md-9" role="main">
 | |
| 
 | |
| <h1 id="examples">Examples</h1>
 | |
| <p>The <a href="https://github.com/machinezone/IXWebSocket/tree/master/ws"><em>ws</em></a> folder countains many interactive programs for chat, <a href="https://github.com/machinezone/IXWebSocket/blob/master/ws/ws_send.cpp">file transfers</a>, <a href="https://github.com/machinezone/IXWebSocket/blob/master/ws/ws_http_client.cpp">curl like</a> http clients, demonstrating client and server usage.</p>
 | |
| <h2 id="windows-note">Windows note</h2>
 | |
| <p>To use the network system on Windows, you need to initialize it once with <em>WSAStartup()</em> and clean it up with <em>WSACleanup()</em>. We have helpers for that which you can use, see below. This init would typically take place in your main function.</p>
 | |
| <pre><code class="cpp">#include <ixwebsocket/IXNetSystem.h>
 | |
| 
 | |
| int main()
 | |
| {
 | |
|     ix::initNetSystem();
 | |
| 
 | |
|     ...
 | |
| 
 | |
|     ix::uninitNetSystem();
 | |
|     return 0;
 | |
| }
 | |
| </code></pre>
 | |
| 
 | |
| <h2 id="websocket-client-api">WebSocket client API</h2>
 | |
| <pre><code class="cpp">#include <ixwebsocket/IXWebSocket.h>
 | |
| 
 | |
| ...
 | |
| 
 | |
| // Our websocket object
 | |
| ix::WebSocket webSocket;
 | |
| 
 | |
| std::string url("ws://localhost:8080/");
 | |
| webSocket.setUrl(url);
 | |
| 
 | |
| // Optional heart beat, sent every 45 seconds when there is not any traffic
 | |
| // to make sure that load balancers do not kill an idle connection.
 | |
| webSocket.setPingInterval(45);
 | |
| 
 | |
| // Per message deflate connection is enabled by default. You can tweak its parameters or disable it
 | |
| webSocket.disablePerMessageDeflate();
 | |
| 
 | |
| // Setup a callback to be fired when a message or an event (open, close, error) is received
 | |
| webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
 | |
|     {
 | |
|         if (msg->type == ix::WebSocketMessageType::Message)
 | |
|         {
 | |
|             std::cout << msg->str << std::endl;
 | |
|         }
 | |
|     }
 | |
| );
 | |
| 
 | |
| // Now that our callback is setup, we can start our background thread and receive messages
 | |
| webSocket.start();
 | |
| 
 | |
| // Send a message to the server (default to TEXT mode)
 | |
| webSocket.send("hello world");
 | |
| 
 | |
| // The message can be sent in BINARY mode (useful if you send MsgPack data for example)
 | |
| webSocket.sendBinary("some serialized binary data");
 | |
| 
 | |
| // ... finally ...
 | |
| 
 | |
| // Stop the connection
 | |
| webSocket.stop()
 | |
| </code></pre>
 | |
| 
 | |
| <h3 id="sending-messages">Sending messages</h3>
 | |
| <p><code>websocket.send("foo")</code> will send a message.</p>
 | |
| <p>If the connection was closed and sending failed, the return value will be set to false.</p>
 | |
| <h3 id="readystate">ReadyState</h3>
 | |
| <p><code>getReadyState()</code> returns the state of the connection. There are 4 possible states.</p>
 | |
| <ol>
 | |
| <li>ReadyState::Connecting - The connection is not yet open.</li>
 | |
| <li>ReadyState::Open       - The connection is open and ready to communicate.</li>
 | |
| <li>ReadyState::Closing    - The connection is in the process of closing.</li>
 | |
| <li>ReadyState::Closed     - The connection is closed or could not be opened.</li>
 | |
| </ol>
 | |
| <h3 id="open-and-close-notifications">Open and Close notifications</h3>
 | |
| <p>The onMessage event will be fired when the connection is opened or closed. This is similar to the <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSocket">JavaScript browser API</a>, which has <code>open</code> and <code>close</code> events notification that can be registered with the browser <code>addEventListener</code>.</p>
 | |
| <pre><code class="cpp">webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
 | |
|     {
 | |
|         if (msg->type == ix::WebSocketMessageType::Open)
 | |
|         {
 | |
|             std::cout << "send greetings" << std::endl;
 | |
| 
 | |
|             // Headers can be inspected (pairs of string/string)
 | |
|             std::cout << "Handshake Headers:" << std::endl;
 | |
|             for (auto it : msg->headers)
 | |
|             {
 | |
|                 std::cout << it.first << ": " << it.second << std::endl;
 | |
|             }
 | |
|         }
 | |
|         else if (msg->type == ix::WebSocketMessageType::Close)
 | |
|         {
 | |
|             std::cout << "disconnected" << std::endl;
 | |
| 
 | |
|             // The server can send an explicit code and reason for closing.
 | |
|             // This data can be accessed through the closeInfo object.
 | |
|             std::cout << msg->closeInfo.code << std::endl;
 | |
|             std::cout << msg->closeInfo.reason << std::endl;
 | |
|         }
 | |
|     }
 | |
| );
 | |
| </code></pre>
 | |
| 
 | |
| <h3 id="error-notification">Error notification</h3>
 | |
| <p>A message will be fired when there is an error with the connection. The message type will be <code>ix::WebSocketMessageType::Error</code>. Multiple fields will be available on the event to describe the error.</p>
 | |
| <pre><code class="cpp">webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
 | |
|     {
 | |
|         if (msg->type == ix::WebSocketMessageType::Error)
 | |
|         {
 | |
|             std::stringstream ss;
 | |
|             ss << "Error: "         << msg->errorInfo.reason      << std::endl;
 | |
|             ss << "#retries: "      << msg->eventInfo.retries     << std::endl;
 | |
|             ss << "Wait time(ms): " << msg->eventInfo.wait_time   << std::endl;
 | |
|             ss << "HTTP Status: "   << msg->eventInfo.http_status << std::endl;
 | |
|             std::cout << ss.str() << std::endl;
 | |
|         }
 | |
|     }
 | |
| );
 | |
| </code></pre>
 | |
| 
 | |
| <h3 id="start-stop">start, stop</h3>
 | |
| <ol>
 | |
| <li><code>websocket.start()</code> connect to the remote server and starts the message receiving background thread.</li>
 | |
| <li><code>websocket.stop()</code> disconnect from the remote server and closes the background thread.</li>
 | |
| </ol>
 | |
| <h3 id="configuring-the-remote-url">Configuring the remote url</h3>
 | |
| <p>The url can be set and queried after a websocket object has been created. You will have to call <code>stop</code> and <code>start</code> if you want to disconnect and connect to that new url.</p>
 | |
| <pre><code class="cpp">std::string url("wss://example.com");
 | |
| websocket.configure(url);
 | |
| </code></pre>
 | |
| 
 | |
| <h3 id="pingpong-support">Ping/Pong support</h3>
 | |
| <p>Ping/pong messages are used to implement keep-alive. 2 message types exists to identify ping and pong messages. Note that when a ping message is received, a pong is instantly send back as requested by the WebSocket spec.</p>
 | |
| <pre><code class="cpp">webSocket.setOnMessageCallback([](const ix::WebSocketMessagePtr& msg)
 | |
|     {
 | |
|         if (msg->type == ix::WebSocketMessageType::Ping ||
 | |
|             msg->type == ix::WebSocketMessageType::Pong)
 | |
|         {
 | |
|             std::cout << "pong data: " << msg->str << std::endl;
 | |
|         }
 | |
|     }
 | |
| );
 | |
| </code></pre>
 | |
| 
 | |
| <p>A ping message can be sent to the server, with an optional data string.</p>
 | |
| <pre><code class="cpp">websocket.ping("ping data, optional (empty string is ok): limited to 125 bytes long");
 | |
| </code></pre>
 | |
| 
 | |
| <h3 id="heartbeat">Heartbeat.</h3>
 | |
| <p>You can configure an optional heart beat / keep-alive, sent every 45 seconds
 | |
| when there is no any traffic to make sure that load balancers do not kill an
 | |
| idle connection.</p>
 | |
| <pre><code class="cpp">webSocket.setPingInterval(45);
 | |
| </code></pre>
 | |
| 
 | |
| <h3 id="supply-extra-http-headers">Supply extra HTTP headers.</h3>
 | |
| <p>You can set extra HTTP headers to be sent during the WebSocket handshake.</p>
 | |
| <pre><code class="cpp">WebSocketHttpHeaders headers;
 | |
| headers["foo"] = "bar";
 | |
| webSocket.setExtraHeaders(headers);
 | |
| </code></pre>
 | |
| 
 | |
| <h3 id="subprotocols">Subprotocols</h3>
 | |
| <p>You can specify subprotocols to be set during the WebSocket handshake. For more info you can refer to <a href="https://hpbn.co/websocket/#subprotocol-negotiation">this doc</a>.</p>
 | |
| <pre><code class="cpp">webSocket.addSubprotocol("appProtocol-v1");
 | |
| webSocket.addSubprotocol("appProtocol-v2");
 | |
| </code></pre>
 | |
| 
 | |
| <p>The protocol that the server did accept is available in the open info <code>protocol</code> field.</p>
 | |
| <pre><code class="cpp">std::cout << "protocol: " << msg->openInfo.protocol << std::endl;
 | |
| </code></pre>
 | |
| 
 | |
| <h3 id="automatic-reconnection">Automatic reconnection</h3>
 | |
| <p>Automatic reconnection kicks in when the connection is disconnected without the user consent. This feature is on by default and can be turned off.</p>
 | |
| <pre><code class="cpp">webSocket.enableAutomaticReconnection();  // turn on
 | |
| webSocket.disableAutomaticReconnection(); // turn off
 | |
| bool enabled = webSocket.isAutomaticReconnectionEnabled(); // query state
 | |
| </code></pre>
 | |
| 
 | |
| <p>The technique to calculate wait time is called <a href="https://docs.aws.amazon.com/general/latest/gr/api-retries.html">exponential
 | |
| backoff</a>. Here
 | |
| are the default waiting times between attempts (from connecting with <code>ws connect ws://foo.com</code>)</p>
 | |
| <pre><code>> Connection error: Got bad status connecting to foo.com, status: 301, HTTP Status line: HTTP/1.1 301 Moved Permanently
 | |
| 
 | |
| #retries: 1
 | |
| Wait time(ms): 100
 | |
| #retries: 2
 | |
| Wait time(ms): 200
 | |
| #retries: 3
 | |
| Wait time(ms): 400
 | |
| #retries: 4
 | |
| Wait time(ms): 800
 | |
| #retries: 5
 | |
| Wait time(ms): 1600
 | |
| #retries: 6
 | |
| Wait time(ms): 3200
 | |
| #retries: 7
 | |
| Wait time(ms): 6400
 | |
| #retries: 8
 | |
| Wait time(ms): 10000
 | |
| </code></pre>
 | |
| 
 | |
| <p>The waiting time is capped by default at 10s between 2 attempts, but that value can be changed and queried.</p>
 | |
| <pre><code class="cpp">webSocket.setMaxWaitBetweenReconnectionRetries(5 * 1000); // 5000ms = 5s
 | |
| uint32_t m = webSocket.getMaxWaitBetweenReconnectionRetries();
 | |
| </code></pre>
 | |
| 
 | |
| <h2 id="websocket-server-api">WebSocket server API</h2>
 | |
| <pre><code class="cpp">#include <ixwebsocket/IXWebSocketServer.h>
 | |
| 
 | |
| ...
 | |
| 
 | |
| // Run a server on localhost at a given port.
 | |
| // Bound host name, max connections and listen backlog can also be passed in as parameters.
 | |
| ix::WebSocketServer server(port);
 | |
| 
 | |
| server.setOnConnectionCallback(
 | |
|     [&server](std::shared_ptr<WebSocket> webSocket,
 | |
|               std::shared_ptr<ConnectionState> connectionState)
 | |
|     {
 | |
|         webSocket->setOnMessageCallback(
 | |
|             [webSocket, connectionState, &server](const ix::WebSocketMessagePtr msg)
 | |
|             {
 | |
|                 if (msg->type == ix::WebSocketMessageType::Open)
 | |
|                 {
 | |
|                     std::cerr << "New connection" << std::endl;
 | |
| 
 | |
|                     // A connection state object is available, and has a default id
 | |
|                     // You can subclass ConnectionState and pass an alternate factory
 | |
|                     // to override it. It is useful if you want to store custom
 | |
|                     // attributes per connection (authenticated bool flag, attributes, etc...)
 | |
|                     std::cerr << "id: " << connectionState->getId() << std::endl;
 | |
| 
 | |
|                     // The uri the client did connect to.
 | |
|                     std::cerr << "Uri: " << msg->openInfo.uri << std::endl;
 | |
| 
 | |
|                     std::cerr << "Headers:" << std::endl;
 | |
|                     for (auto it : msg->openInfo.headers)
 | |
|                     {
 | |
|                         std::cerr << it.first << ": " << it.second << std::endl;
 | |
|                     }
 | |
|                 }
 | |
|                 else if (msg->type == ix::WebSocketMessageType::Message)
 | |
|                 {
 | |
|                     // For an echo server, we just send back to the client whatever was received by the server
 | |
|                     // All connected clients are available in an std::set. See the broadcast cpp example.
 | |
|                     // Second parameter tells whether we are sending the message in binary or text mode.
 | |
|                     // Here we send it in the same mode as it was received.
 | |
|                     webSocket->send(msg->str, msg->binary);
 | |
|                 }
 | |
|             }
 | |
|         );
 | |
|     }
 | |
| );
 | |
| 
 | |
| auto res = server.listen();
 | |
| if (!res.first)
 | |
| {
 | |
|     // Error handling
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| // Run the server in the background. Server can be stoped by calling server.stop()
 | |
| server.start();
 | |
| 
 | |
| // Block until server.stop() is called.
 | |
| server.wait();
 | |
| 
 | |
| </code></pre>
 | |
| 
 | |
| <h2 id="http-client-api">HTTP client API</h2>
 | |
| <pre><code class="cpp">#include <ixwebsocket/IXHttpClient.h>
 | |
| 
 | |
| ...
 | |
| 
 | |
| //
 | |
| // Preparation
 | |
| //
 | |
| HttpClient httpClient;
 | |
| HttpRequestArgsPtr args = httpClient.createRequest();
 | |
| 
 | |
| // Custom headers can be set
 | |
| WebSocketHttpHeaders headers;
 | |
| headers["Foo"] = "bar";
 | |
| args->extraHeaders = headers;
 | |
| 
 | |
| // Timeout options
 | |
| args->connectTimeout = connectTimeout;
 | |
| args->transferTimeout = transferTimeout;
 | |
| 
 | |
| // Redirect options
 | |
| args->followRedirects = followRedirects;
 | |
| args->maxRedirects = maxRedirects;
 | |
| 
 | |
| // Misc
 | |
| args->compress = compress; // Enable gzip compression
 | |
| args->verbose = verbose;
 | |
| args->logger = [](const std::string& msg)
 | |
| {
 | |
|     std::cout << msg;
 | |
| };
 | |
| 
 | |
| //
 | |
| // Synchronous Request
 | |
| //
 | |
| HttpResponsePtr out;
 | |
| std::string url = "https://www.google.com";
 | |
| 
 | |
| // HEAD request
 | |
| out = httpClient.head(url, args);
 | |
| 
 | |
| // GET request
 | |
| out = httpClient.get(url, args);
 | |
| 
 | |
| // POST request with parameters
 | |
| HttpParameters httpParameters;
 | |
| httpParameters["foo"] = "bar";
 | |
| out = httpClient.post(url, httpParameters, args);
 | |
| 
 | |
| // POST request with a body
 | |
| out = httpClient.post(url, std::string("foo=bar"), args);
 | |
| 
 | |
| //
 | |
| // Result
 | |
| //
 | |
| auto statusCode = response->statusCode; // Can be HttpErrorCode::Ok, HttpErrorCode::UrlMalformed, etc...
 | |
| auto errorCode = response->errorCode; // 200, 404, etc...
 | |
| auto responseHeaders = response->headers; // All the headers in a special case-insensitive unordered_map of (string, string)
 | |
| auto payload = response->payload; // All the bytes from the response as an std::string
 | |
| auto errorMsg = response->errorMsg; // Descriptive error message in case of failure
 | |
| auto uploadSize = response->uploadSize; // Byte count of uploaded data
 | |
| auto downloadSize = response->downloadSize; // Byte count of downloaded data
 | |
| 
 | |
| //
 | |
| // Asynchronous Request
 | |
| //
 | |
| bool async = true;
 | |
| HttpClient httpClient(async);
 | |
| auto args = httpClient.createRequest(url, HttpClient::kGet);
 | |
| 
 | |
| // Push the request to a queue,
 | |
| bool ok = httpClient.performRequest(args, [](const HttpResponsePtr& response)
 | |
|     {
 | |
|         // This callback execute in a background thread. Make sure you uses appropriate protection such as mutex
 | |
|         auto statusCode = response->statusCode; // acess results
 | |
|     }
 | |
| );
 | |
| 
 | |
| // ok will be false if your httpClient is not async
 | |
| </code></pre>
 | |
| 
 | |
| <p>See this <a href="https://github.com/machinezone/IXWebSocket/issues/209">issue</a> for links about uploading files with HTTP multipart.</p>
 | |
| <h2 id="http-server-api">HTTP server API</h2>
 | |
| <pre><code class="cpp">#include <ixwebsocket/IXHttpServer.h>
 | |
| 
 | |
| ix::HttpServer server(port, hostname);
 | |
| 
 | |
| auto res = server.listen();
 | |
| if (!res.first)
 | |
| {
 | |
|     std::cerr << res.second << std::endl;
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| server.start();
 | |
| server.wait();
 | |
| </code></pre>
 | |
| 
 | |
| <p>If you want to handle how requests are processed, implement the setOnConnectionCallback callback, which takes an HttpRequestPtr as input, and returns an HttpResponsePtr. You can look at HttpServer::setDefaultConnectionCallback for a slightly more advanced callback example.</p>
 | |
| <pre><code class="cpp">setOnConnectionCallback(
 | |
|     [this](HttpRequestPtr request,
 | |
|            std::shared_ptr<ConnectionState> /*connectionState*/) -> HttpResponsePtr
 | |
|     {
 | |
|         // Build a string for the response
 | |
|         std::stringstream ss;
 | |
|         ss << request->method
 | |
|            << " "
 | |
|            << request->uri;
 | |
| 
 | |
|         std::string content = ss.str();
 | |
| 
 | |
|         return std::make_shared<HttpResponse>(200, "OK",
 | |
|                                               HttpErrorCode::Ok,
 | |
|                                               WebSocketHttpHeaders(),
 | |
|                                               content);
 | |
| }
 | |
| </code></pre>
 | |
| 
 | |
| <h2 id="tls-support-and-configuration">TLS support and configuration</h2>
 | |
| <p>To leverage TLS features, the library must be compiled with the option <code>USE_TLS=1</code>.</p>
 | |
| <p>If you are using OpenSSL, try to be on a version higher than 1.1.x as there there are thread safety problems with 1.0.x.</p>
 | |
| <p>Then, secure sockets are automatically used when connecting to a <code>wss://*</code> url.</p>
 | |
| <p>Additional TLS options can be configured by passing a <code>ix::SocketTLSOptions</code> instance to the
 | |
| <code>setTLSOptions</code> on <code>ix::WebSocket</code> (or <code>ix::WebSocketServer</code> or <code>ix::HttpServer</code>)</p>
 | |
| <pre><code class="cpp">webSocket.setTLSOptions({
 | |
|     .certFile = "path/to/cert/file.pem",
 | |
|     .keyFile = "path/to/key/file.pem",
 | |
|     .caFile = "path/to/trust/bundle/file.pem", // as a file, or in memory buffer in PEM format
 | |
|     .tls = true // required in server mode
 | |
| });
 | |
| </code></pre>
 | |
| 
 | |
| <p>Specifying <code>certFile</code> and <code>keyFile</code> configures the certificate that will be used to communicate with TLS peers.</p>
 | |
| <p>On a client, this is only necessary for connecting to servers that require a client certificate.</p>
 | |
| <p>On a server, this is necessary for TLS support.</p>
 | |
| <p>Specifying <code>caFile</code> configures the trusted roots bundle file (in PEM format) that will be used to verify peer certificates.
 | |
|  - The special value of <code>SYSTEM</code> (the default) indicates that the system-configured trust bundle should be used; this is generally what you want when connecting to any publicly exposed API/server.
 | |
|  - The special value of <code>NONE</code> can be used to disable peer verification; this is only recommended to rule out certificate verification when testing connectivity.
 | |
|  - If the value contain the special value <code>-----BEGIN CERTIFICATE-----</code>, the value will be read from memory, and not from a file. This is convenient on platforms like Android where reading / writing to the file system can be challenging without proper permissions, or without knowing the location of a temp directory.</p>
 | |
| <p>For a client, specifying <code>caFile</code> can be used if connecting to a server that uses a self-signed cert, or when using a custom CA in an internal environment.</p>
 | |
| <p>For a server, specifying <code>caFile</code> implies that:
 | |
| 1. You require clients to present a certificate
 | |
| 1. It must be signed by one of the trusted roots in the file</p></div>
 | |
|             </div>
 | |
|         </div>
 | |
| 
 | |
|         <footer class="col-md-12">
 | |
|             <hr>
 | |
|             <p>Documentation built with <a href="https://www.mkdocs.org/">MkDocs</a>.</p>
 | |
|         </footer>
 | |
|         <script>
 | |
|             var base_url = "..",
 | |
|                 shortcuts = {"help": 191, "next": 78, "previous": 80, "search": 83};
 | |
|         </script>
 | |
|         <script src="../js/base.js" defer></script>
 | |
|         <script src="../search/main.js" defer></script>
 | |
| 
 | |
|         <div class="modal" id="mkdocs_search_modal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel" aria-hidden="true">
 | |
|     <div class="modal-dialog modal-lg">
 | |
|         <div class="modal-content">
 | |
|             <div class="modal-header">
 | |
|                 <h4 class="modal-title" id="searchModalLabel">Search</h4>
 | |
|                 <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
 | |
|             </div>
 | |
|             <div class="modal-body">
 | |
|                 <p>
 | |
|                     From here you can search these documents. Enter
 | |
|                     your search terms below.
 | |
|                 </p>
 | |
|                 <form>
 | |
|                     <div class="form-group">
 | |
|                         <input type="search" class="form-control" placeholder="Search..." id="mkdocs-search-query" title="Type search term here">
 | |
|                     </div>
 | |
|                 </form>
 | |
|                 <div id="mkdocs-search-results"></div>
 | |
|             </div>
 | |
|             <div class="modal-footer">
 | |
|             </div>
 | |
|         </div>
 | |
|     </div>
 | |
| </div><div class="modal" id="mkdocs_keyboard_modal" tabindex="-1" role="dialog" aria-labelledby="keyboardModalLabel" aria-hidden="true">
 | |
|     <div class="modal-dialog">
 | |
|         <div class="modal-content">
 | |
|             <div class="modal-header">
 | |
|                 <h4 class="modal-title" id="keyboardModalLabel">Keyboard Shortcuts</h4>
 | |
|                 <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
 | |
|             </div>
 | |
|             <div class="modal-body">
 | |
|               <table class="table">
 | |
|                 <thead>
 | |
|                   <tr>
 | |
|                     <th style="width: 20%;">Keys</th>
 | |
|                     <th>Action</th>
 | |
|                   </tr>
 | |
|                 </thead>
 | |
|                 <tbody>
 | |
|                   <tr>
 | |
|                     <td class="help shortcut"><kbd>?</kbd></td>
 | |
|                     <td>Open this help</td>
 | |
|                   </tr>
 | |
|                   <tr>
 | |
|                     <td class="next shortcut"><kbd>n</kbd></td>
 | |
|                     <td>Next page</td>
 | |
|                   </tr>
 | |
|                   <tr>
 | |
|                     <td class="prev shortcut"><kbd>p</kbd></td>
 | |
|                     <td>Previous page</td>
 | |
|                   </tr>
 | |
|                   <tr>
 | |
|                     <td class="search shortcut"><kbd>s</kbd></td>
 | |
|                     <td>Search</td>
 | |
|                   </tr>
 | |
|                 </tbody>
 | |
|               </table>
 | |
|             </div>
 | |
|             <div class="modal-footer">
 | |
|             </div>
 | |
|         </div>
 | |
|     </div>
 | |
| </div>
 | |
| 
 | |
|     </body>
 | |
| </html>
 | 
