blob: a516edd6f4345a713e8db96d26b29ec343837b53 [file] [log] [blame]
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -06001#pragma once
2
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08003#include "app.hpp"
Ed Tanous36c0f2a2024-02-09 13:50:26 -08004#include "dbus_utility.hpp"
5#include "privileges.hpp"
Ed Tanousfaf100f2023-05-25 10:03:14 -07006#include "websocket.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08007
Ed Tanous36c0f2a2024-02-09 13:50:26 -08008#include <boost/asio/local/stream_protocol.hpp>
Ed Tanous3bfa3b22024-01-31 12:18:03 -08009#include <boost/asio/readable_pipe.hpp>
10#include <boost/asio/writable_pipe.hpp>
Ed Tanous36c0f2a2024-02-09 13:50:26 -080011#include <boost/asio/write.hpp>
12#include <boost/beast/core/buffers_to_string.hpp>
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060013#include <boost/beast/core/flat_static_buffer.hpp>
Ed Tanous36c0f2a2024-02-09 13:50:26 -080014#include <boost/container/flat_map.hpp>
Ed Tanous3bfa3b22024-01-31 12:18:03 -080015#include <boost/process/v2/process.hpp>
16#include <boost/process/v2/stdio.hpp>
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060017
Gunnar Mills1214b7e2020-06-04 10:11:30 -050018#include <csignal>
Ed Tanous36c0f2a2024-02-09 13:50:26 -080019#include <string_view>
Gunnar Mills1214b7e2020-06-04 10:11:30 -050020
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060021namespace crow
22{
Ed Tanous36c0f2a2024-02-09 13:50:26 -080023
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060024namespace obmc_vm
25{
26
Ed Tanouscf9e4172022-12-21 09:30:16 -080027// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060028static crow::websocket::Connection* session = nullptr;
29
30// The max network block device buffer size is 128kb plus 16bytes
31// for the message header:
32// https://github.com/NetworkBlockDevice/nbd/blob/master/doc/proto.md#simple-reply-message
Troy Lee4ee8f0b2021-08-02 11:08:26 +080033static constexpr auto nbdBufferSize = (128 * 1024 + 16) * 4;
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060034
35class Handler : public std::enable_shared_from_this<Handler>
36{
37 public:
Ed Tanous3bfa3b22024-01-31 12:18:03 -080038 Handler(const std::string& media, boost::asio::io_context& ios) :
39 pipeOut(ios), pipeIn(ios),
40 proxy(ios, "/usr/bin/nbd-proxy", {media},
41 boost::process::v2::process_stdio{
42 .in = pipeIn, .out = pipeOut, .err = nullptr}),
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060043 outputBuffer(new boost::beast::flat_static_buffer<nbdBufferSize>),
44 inputBuffer(new boost::beast::flat_static_buffer<nbdBufferSize>)
Gunnar Mills1214b7e2020-06-04 10:11:30 -050045 {}
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060046
Ed Tanous0c0084a2019-10-24 15:57:51 -070047 ~Handler() = default;
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060048
Ed Tanousecd6a3a2022-01-07 09:18:40 -080049 Handler(const Handler&) = delete;
50 Handler(Handler&&) = delete;
51 Handler& operator=(const Handler&) = delete;
52 Handler& operator=(Handler&&) = delete;
53
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060054 void doClose()
55 {
56 // boost::process::child::terminate uses SIGKILL, need to send SIGTERM
57 // to allow the proxy to stop nbd-client and the USB device gadget.
58 int rc = kill(proxy.id(), SIGTERM);
Ed Tanouse662eae2022-01-25 10:39:19 -080059 if (rc != 0)
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060060 {
Ed Tanous62598e32023-07-17 17:06:25 -070061 BMCWEB_LOG_ERROR("Failed to terminate nbd-proxy: {}", errno);
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060062 return;
63 }
Troy Lee36ecbf32021-08-17 18:15:28 +080064
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060065 proxy.wait();
66 }
67
68 void connect()
69 {
70 std::error_code ec;
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060071 if (ec)
72 {
Ed Tanous62598e32023-07-17 17:06:25 -070073 BMCWEB_LOG_ERROR("Couldn't connect to nbd-proxy: {}", ec.message());
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060074 if (session != nullptr)
75 {
76 session->close("Error connecting to nbd-proxy");
77 }
78 return;
79 }
80 doWrite();
81 doRead();
82 }
83
84 void doWrite()
85 {
86 if (doingWrite)
87 {
Ed Tanous62598e32023-07-17 17:06:25 -070088 BMCWEB_LOG_DEBUG("Already writing. Bailing out");
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060089 return;
90 }
91
92 if (inputBuffer->size() == 0)
93 {
Ed Tanous62598e32023-07-17 17:06:25 -070094 BMCWEB_LOG_DEBUG("inputBuffer empty. Bailing out");
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -060095 return;
96 }
97
98 doingWrite = true;
99 pipeIn.async_write_some(
100 inputBuffer->data(),
Ed Tanous81c4e332023-05-18 10:30:34 -0700101 [this, self(shared_from_this())](const boost::beast::error_code& ec,
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600102 std::size_t bytesWritten) {
Ed Tanous62598e32023-07-17 17:06:25 -0700103 BMCWEB_LOG_DEBUG("Wrote {}bytes", bytesWritten);
Ed Tanous002d39b2022-05-31 08:59:27 -0700104 doingWrite = false;
105 inputBuffer->consume(bytesWritten);
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600106
Ed Tanous002d39b2022-05-31 08:59:27 -0700107 if (session == nullptr)
108 {
109 return;
110 }
111 if (ec == boost::asio::error::eof)
112 {
113 session->close("VM socket port closed");
114 return;
115 }
116 if (ec)
117 {
118 session->close("Error in writing to proxy port");
Ed Tanous62598e32023-07-17 17:06:25 -0700119 BMCWEB_LOG_ERROR("Error in VM socket write {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -0700120 return;
121 }
122 doWrite();
Patrick Williams5a39f772023-10-20 11:20:21 -0500123 });
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600124 }
125
126 void doRead()
127 {
128 std::size_t bytes = outputBuffer->capacity() - outputBuffer->size();
129
130 pipeOut.async_read_some(
131 outputBuffer->prepare(bytes),
132 [this, self(shared_from_this())](
133 const boost::system::error_code& ec, std::size_t bytesRead) {
Ed Tanous62598e32023-07-17 17:06:25 -0700134 BMCWEB_LOG_DEBUG("Read done. Read {} bytes", bytesRead);
Ed Tanous002d39b2022-05-31 08:59:27 -0700135 if (ec)
136 {
Ed Tanous62598e32023-07-17 17:06:25 -0700137 BMCWEB_LOG_ERROR("Couldn't read from VM port: {}", ec);
Ed Tanous002d39b2022-05-31 08:59:27 -0700138 if (session != nullptr)
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600139 {
Ed Tanous002d39b2022-05-31 08:59:27 -0700140 session->close("Error in connecting to VM port");
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600141 }
Ed Tanous002d39b2022-05-31 08:59:27 -0700142 return;
143 }
144 if (session == nullptr)
145 {
146 return;
147 }
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600148
Ed Tanous002d39b2022-05-31 08:59:27 -0700149 outputBuffer->commit(bytesRead);
150 std::string_view payload(
151 static_cast<const char*>(outputBuffer->data().data()),
152 bytesRead);
153 session->sendBinary(payload);
154 outputBuffer->consume(bytesRead);
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600155
Ed Tanous002d39b2022-05-31 08:59:27 -0700156 doRead();
Patrick Williams5a39f772023-10-20 11:20:21 -0500157 });
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600158 }
159
Ed Tanous3bfa3b22024-01-31 12:18:03 -0800160 boost::asio::readable_pipe pipeOut;
161 boost::asio::writable_pipe pipeIn;
162 boost::process::v2::process proxy;
Ed Tanousf5b191a2022-02-15 11:30:39 -0800163 bool doingWrite{false};
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600164
165 std::unique_ptr<boost::beast::flat_static_buffer<nbdBufferSize>>
166 outputBuffer;
167 std::unique_ptr<boost::beast::flat_static_buffer<nbdBufferSize>>
168 inputBuffer;
169};
170
Ed Tanouscf9e4172022-12-21 09:30:16 -0800171// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600172static std::shared_ptr<Handler> handler;
173
Ed Tanous36c0f2a2024-02-09 13:50:26 -0800174} // namespace obmc_vm
175
176namespace nbd_proxy
177{
178using boost::asio::local::stream_protocol;
179
180// The max network block device buffer size is 128kb plus 16bytes
181// for the message header:
182// https://github.com/NetworkBlockDevice/nbd/blob/master/doc/proto.md#simple-reply-message
183static constexpr auto nbdBufferSize = (128 * 1024 + 16) * 4;
184
185struct NbdProxyServer : std::enable_shared_from_this<NbdProxyServer>
186{
187 NbdProxyServer(crow::websocket::Connection& connIn,
188 const std::string& socketIdIn,
189 const std::string& endpointIdIn, const std::string& pathIn) :
190 socketId(socketIdIn),
191 endpointId(endpointIdIn), path(pathIn),
192
193 peerSocket(connIn.getIoContext()),
194 acceptor(connIn.getIoContext(), stream_protocol::endpoint(socketId)),
195 connection(connIn)
196 {}
197
198 NbdProxyServer(const NbdProxyServer&) = delete;
199 NbdProxyServer(NbdProxyServer&&) = delete;
200 NbdProxyServer& operator=(const NbdProxyServer&) = delete;
201 NbdProxyServer& operator=(NbdProxyServer&&) = delete;
202
203 ~NbdProxyServer()
204 {
205 BMCWEB_LOG_DEBUG("NbdProxyServer destructor");
206
207 BMCWEB_LOG_DEBUG("peerSocket->close()");
208 boost::system::error_code ec;
209 peerSocket.close(ec);
210
211 BMCWEB_LOG_DEBUG("std::filesystem::remove({})", socketId);
212 std::error_code ec2;
213 std::filesystem::remove(socketId.c_str(), ec2);
214 if (ec2)
215 {
216 BMCWEB_LOG_DEBUG("Failed to remove file, ignoring");
217 }
218
219 crow::connections::systemBus->async_method_call(
220 dbus::utility::logError, "xyz.openbmc_project.VirtualMedia", path,
221 "xyz.openbmc_project.VirtualMedia.Proxy", "Unmount");
222 }
223
224 std::string getEndpointId() const
225 {
226 return endpointId;
227 }
228
229 void run()
230 {
231 acceptor.async_accept(
232 [weak(weak_from_this())](const boost::system::error_code& ec,
233 stream_protocol::socket socket) {
234 if (ec)
235 {
236 BMCWEB_LOG_ERROR("UNIX socket: async_accept error = {}",
237 ec.message());
238 return;
239 }
240
241 BMCWEB_LOG_DEBUG("Connection opened");
242 std::shared_ptr<NbdProxyServer> self = weak.lock();
243 if (self == nullptr)
244 {
245 return;
246 }
247
248 self->connection.resumeRead();
249 self->peerSocket = std::move(socket);
250 // Start reading from socket
251 self->doRead();
252 });
253
254 auto mountHandler = [weak(weak_from_this())](
255 const boost::system::error_code& ec, bool) {
256 std::shared_ptr<NbdProxyServer> self = weak.lock();
257 if (self == nullptr)
258 {
259 return;
260 }
261 if (ec)
262 {
263 BMCWEB_LOG_ERROR("DBus error: cannot call mount method = {}",
264 ec.message());
265
266 self->connection.close("Failed to mount media");
267 return;
268 }
269 };
270
271 crow::connections::systemBus->async_method_call(
272 std::move(mountHandler), "xyz.openbmc_project.VirtualMedia", path,
273 "xyz.openbmc_project.VirtualMedia.Proxy", "Mount");
274 }
275
276 void send(std::string_view buffer, std::function<void()>&& onDone)
277 {
278 size_t copied = boost::asio::buffer_copy(
279 ws2uxBuf.prepare(buffer.size()), boost::asio::buffer(buffer));
280 ws2uxBuf.commit(copied);
281
282 doWrite(std::move(onDone));
283 }
284
285 private:
286 void doRead()
287 {
288 // Trigger async read
289 peerSocket.async_read_some(
290 ux2wsBuf.prepare(nbdBufferSize),
291 [weak(weak_from_this())](const boost::system::error_code& ec,
292 size_t bytesRead) {
293 if (ec)
294 {
295 BMCWEB_LOG_ERROR("UNIX socket: async_read_some error = {}",
296 ec.message());
297 return;
298 }
299 std::shared_ptr<NbdProxyServer> self = weak.lock();
300 if (self == nullptr)
301 {
302 return;
303 }
304
305 // Send to websocket
306 self->ux2wsBuf.commit(bytesRead);
307 self->connection.sendEx(
308 crow::websocket::MessageType::Binary,
309 boost::beast::buffers_to_string(self->ux2wsBuf.data()),
310 [weak(self->weak_from_this())]() {
311 std::shared_ptr<NbdProxyServer> self2 = weak.lock();
312 if (self2 != nullptr)
313 {
314 self2->ux2wsBuf.consume(self2->ux2wsBuf.size());
315 self2->doRead();
316 }
317 });
318 });
319 }
320
321 void doWrite(std::function<void()>&& onDone)
322 {
323 if (uxWriteInProgress)
324 {
325 BMCWEB_LOG_ERROR("Write in progress");
326 return;
327 }
328
329 if (ws2uxBuf.size() == 0)
330 {
331 BMCWEB_LOG_ERROR("No data to write to UNIX socket");
332 return;
333 }
334
335 uxWriteInProgress = true;
336 peerSocket.async_write_some(
337 ws2uxBuf.data(),
338 [weak(weak_from_this()),
339 onDone(std::move(onDone))](const boost::system::error_code& ec,
340 size_t bytesWritten) mutable {
341 std::shared_ptr<NbdProxyServer> self = weak.lock();
342 if (self == nullptr)
343 {
344 return;
345 }
346
347 self->ws2uxBuf.consume(bytesWritten);
348 self->uxWriteInProgress = false;
349
350 if (ec)
351 {
352 BMCWEB_LOG_ERROR("UNIX: async_write error = {}", ec.message());
353 self->connection.close("Internal error");
354 return;
355 }
356
357 // Retrigger doWrite if there is something in buffer
358 if (self->ws2uxBuf.size() > 0)
359 {
360 self->doWrite(std::move(onDone));
361 return;
362 }
363 onDone();
364 });
365 }
366
367 // Keeps UNIX socket endpoint file path
368 const std::string socketId;
369 const std::string endpointId;
370 const std::string path;
371
372 bool uxWriteInProgress = false;
373
374 // UNIX => WebSocket buffer
375 boost::beast::flat_static_buffer<nbdBufferSize> ux2wsBuf;
376
377 // WebSocket => UNIX buffer
378 boost::beast::flat_static_buffer<nbdBufferSize> ws2uxBuf;
379
380 // The socket used to communicate with the client.
381 stream_protocol::socket peerSocket;
382
383 // Default acceptor for UNIX socket
384 stream_protocol::acceptor acceptor;
385
386 crow::websocket::Connection& connection;
387};
388
389using SessionMap = boost::container::flat_map<crow::websocket::Connection*,
390 std::shared_ptr<NbdProxyServer>>;
391// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
392static SessionMap sessions;
393
394inline void
395 afterGetManagedObjects(crow::websocket::Connection& conn,
396 const boost::system::error_code& ec,
397 const dbus::utility::ManagedObjectType& objects)
398{
399 const std::string* socketValue = nullptr;
400 const std::string* endpointValue = nullptr;
401 const std::string* endpointObjectPath = nullptr;
402
403 if (ec)
404 {
405 BMCWEB_LOG_ERROR("DBus error: {}", ec.message());
406 conn.close("Failed to create mount point");
407 return;
408 }
409
410 for (const auto& [objectPath, interfaces] : objects)
411 {
412 for (const auto& [interface, properties] : interfaces)
413 {
414 if (interface != "xyz.openbmc_project.VirtualMedia.MountPoint")
415 {
416 continue;
417 }
418
419 for (const auto& [name, value] : properties)
420 {
421 if (name == "EndpointId")
422 {
423 endpointValue = std::get_if<std::string>(&value);
424
425 if (endpointValue == nullptr)
426 {
427 BMCWEB_LOG_ERROR("EndpointId property value is null");
428 }
429 }
430 if (name == "Socket")
431 {
432 socketValue = std::get_if<std::string>(&value);
433 if (socketValue == nullptr)
434 {
435 BMCWEB_LOG_ERROR("Socket property value is null");
436 }
437 }
438 }
439 }
440
441 if ((endpointValue != nullptr) && (socketValue != nullptr) &&
442 *endpointValue == conn.url().path())
443 {
444 endpointObjectPath = &objectPath.str;
445 break;
446 }
447 }
448
449 if (objects.empty() || endpointObjectPath == nullptr)
450 {
451 BMCWEB_LOG_ERROR("Cannot find requested EndpointId");
452 conn.close("Failed to match EndpointId");
453 return;
454 }
455
456 for (const auto& session : sessions)
457 {
458 if (session.second->getEndpointId() == conn.url().path())
459 {
460 BMCWEB_LOG_ERROR("Cannot open new connection - socket is in use");
461 conn.close("Slot is in use");
462 return;
463 }
464 }
465
466 // If the socket file exists (i.e. after bmcweb crash),
467 // we cannot reuse it.
468 std::remove((*socketValue).c_str());
469
470 sessions[&conn] = std::make_shared<NbdProxyServer>(
471 conn, *socketValue, *endpointValue, *endpointObjectPath);
472
473 sessions[&conn]->run();
474};
475
476inline void onOpen(crow::websocket::Connection& conn)
477{
478 BMCWEB_LOG_DEBUG("nbd-proxy.onopen({})", logPtr(&conn));
479
480 sdbusplus::message::object_path path("/xyz/openbmc_project/VirtualMedia");
481 dbus::utility::getManagedObjects(
482 "xyz.openbmc_project.VirtualMedia", path,
483 [&conn](const boost::system::error_code& ec,
484 const dbus::utility::ManagedObjectType& objects) {
485 afterGetManagedObjects(conn, ec, objects);
486 });
487
488 // We need to wait for dbus and the websockets to hook up before data is
489 // sent/received. Tell the core to hold off messages until the sockets are
490 // up
491 conn.deferRead();
492}
493
494inline void onClose(crow::websocket::Connection& conn,
495 const std::string& reason)
496{
497 BMCWEB_LOG_DEBUG("nbd-proxy.onclose(reason = '{}')", reason);
498 auto session = sessions.find(&conn);
499 if (session == sessions.end())
500 {
501 BMCWEB_LOG_DEBUG("No session to close");
502 return;
503 }
504 // Remove reference to session in global map
505 sessions.erase(session);
506}
507
508inline void onMessage(crow::websocket::Connection& conn, std::string_view data,
509 crow::websocket::MessageType /*type*/,
510 std::function<void()>&& whenComplete)
511{
512 BMCWEB_LOG_DEBUG("nbd-proxy.onMessage(len = {})", data.size());
513
514 // Acquire proxy from sessions
515 auto session = sessions.find(&conn);
516 if (session == sessions.end() || session->second == nullptr)
517 {
518 whenComplete();
519 return;
520 }
521
522 session->second->send(data, std::move(whenComplete));
523}
524
Ed Tanous23a21a12020-07-25 04:45:05 +0000525inline void requestRoutes(App& app)
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600526{
Ed Tanous36c0f2a2024-02-09 13:50:26 -0800527 BMCWEB_ROUTE(app, "/nbd/<str>")
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600528 .websocket()
Ed Tanous36c0f2a2024-02-09 13:50:26 -0800529 .onopen(onOpen)
530 .onclose(onClose)
531 .onmessageex(onMessage);
532}
533} // namespace nbd_proxy
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600534
Ed Tanous36c0f2a2024-02-09 13:50:26 -0800535namespace obmc_vm
536{
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600537
Ed Tanous36c0f2a2024-02-09 13:50:26 -0800538inline void requestRoutes(App& app)
539{
540 static_assert(
541 !(bmcwebVmWebsocket && bmcwebNbdProxy),
542 "nbd proxy cannot be turned on at the same time as vm websocket.");
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600543
Ed Tanous36c0f2a2024-02-09 13:50:26 -0800544 if constexpr (bmcwebVmWebsocket)
545 {
546 BMCWEB_ROUTE(app, "/nbd/<str>")
547 .privileges({{"ConfigureComponents", "ConfigureManager"}})
548 .websocket()
549 .onopen(nbd_proxy::onOpen)
550 .onclose(nbd_proxy::onClose)
551 .onmessageex(nbd_proxy::onMessage);
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600552
Ed Tanous36c0f2a2024-02-09 13:50:26 -0800553 BMCWEB_ROUTE(app, "/vm/0/0")
554 .privileges({{"ConfigureComponents", "ConfigureManager"}})
555 .websocket()
556 .onopen(nbd_proxy::onOpen)
557 .onclose(nbd_proxy::onClose)
558 .onmessageex(nbd_proxy::onMessage);
559 }
560 if constexpr (bmcwebNbdProxy)
561 {
562 BMCWEB_ROUTE(app, "/vm/0/0")
563 .privileges({{"ConfigureComponents", "ConfigureManager"}})
564 .websocket()
565 .onopen([](crow::websocket::Connection& conn) {
566 BMCWEB_LOG_DEBUG("Connection {} opened", logPtr(&conn));
Ed Tanouscb13a392020-07-25 19:02:03 +0000567
Ed Tanous36c0f2a2024-02-09 13:50:26 -0800568 if (session != nullptr)
569 {
570 conn.close("Session already connected");
571 return;
572 }
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600573
Ed Tanous36c0f2a2024-02-09 13:50:26 -0800574 if (handler != nullptr)
575 {
576 conn.close("Handler already running");
577 return;
578 }
579
580 session = &conn;
581
582 // media is the last digit of the endpoint /vm/0/0. A future
583 // enhancement can include supporting different endpoint values.
584 const char* media = "0";
585 handler = std::make_shared<Handler>(media, conn.getIoContext());
586 handler->connect();
587 })
588 .onclose([](crow::websocket::Connection& conn,
589 const std::string& /*reason*/) {
590 if (&conn != session)
591 {
592 return;
593 }
594
595 session = nullptr;
596 handler->doClose();
597 handler->inputBuffer->clear();
598 handler->outputBuffer->clear();
599 handler.reset();
600 })
601 .onmessage([](crow::websocket::Connection& conn,
602 const std::string& data, bool) {
603 if (data.length() >
604 handler->inputBuffer->capacity() - handler->inputBuffer->size())
605 {
606 BMCWEB_LOG_ERROR("Buffer overrun when writing {} bytes",
607 data.length());
608 conn.close("Buffer overrun");
609 return;
610 }
611
Ed Tanous44106f32024-04-06 13:48:50 -0700612 boost::asio::buffer_copy(handler->inputBuffer->prepare(data.size()),
613 boost::asio::buffer(data));
Ed Tanous36c0f2a2024-02-09 13:50:26 -0800614 handler->inputBuffer->commit(data.size());
615 handler->doWrite();
616 });
617 }
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600618}
619
620} // namespace obmc_vm
Ed Tanous36c0f2a2024-02-09 13:50:26 -0800621
Adriana Kobylak1bfbe0e2019-01-17 12:08:38 -0600622} // namespace crow