blob: 2a959677df400725c2b64dabef093181cc506301 [file] [log] [blame]
Ed Tanousc3ee5222018-05-01 12:58:27 -07001#pragma once
2
3#include <dbus_singleton.hpp>
4#include <cstdio>
5#include <fstream>
6#include <memory>
7#include <crow/app.h>
8#include <boost/uuid/uuid.hpp>
9#include <boost/uuid/uuid_generators.hpp>
10#include <boost/uuid/uuid_io.hpp>
11
12namespace crow {
13namespace image_upload {
14
15std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher;
16
17inline void uploadImageHandler(const crow::request& req, crow::response& res,
18 const std::string& filename) {
19 // Only allow one FW update at a time
20 if (fwUpdateMatcher != nullptr) {
21 res.add_header("Retry-After", "30");
22 res.result(boost::beast::http::status::service_unavailable);
23 res.end();
24 return;
25 }
26 // Make this const static so it survives outside this method
27 static boost::asio::deadline_timer timeout(*req.io_service,
28 boost::posix_time::seconds(5));
29
30 timeout.expires_from_now(boost::posix_time::seconds(5));
31
32 timeout.async_wait([&res](const boost::system::error_code& ec) {
33 fwUpdateMatcher = nullptr;
34 if (ec == asio::error::operation_aborted) {
35 // expected, we were canceled before the timer completed.
36 return;
37 }
38 CROW_LOG_ERROR << "Timed out waiting for log event";
39
40 if (ec) {
41 CROW_LOG_ERROR << "Async_wait failed " << ec;
42 return;
43 }
44
45 res.result(boost::beast::http::status::internal_server_error);
46 res.end();
47 });
48
49 std::function<void(sdbusplus::message::message&)> callback =
50 [&res](sdbusplus::message::message& m) {
51 CROW_LOG_DEBUG << "Match fired";
52 boost::system::error_code ec;
53 timeout.cancel(ec);
54 if (ec) {
55 CROW_LOG_ERROR << "error canceling timer " << ec;
56 }
57 std::string versionInfo;
58 m.read(versionInfo); // Read in the object path that was just created
59
60 std::size_t index = versionInfo.rfind('/');
61 if (index != std::string::npos) {
62 versionInfo.erase(0, index);
63 }
64 res.json_value = {{"data", std::move(versionInfo)},
65 {"message", "200 OK"},
66 {"status", "ok"}};
67 CROW_LOG_DEBUG << "ending response";
68 res.end();
69 fwUpdateMatcher = nullptr;
70 };
71 fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
72 *crow::connections::system_bus,
73 "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
74 "member='InterfacesAdded',path='/xyz/openbmc_project/logging'",
75 callback);
76
77 std::string filepath(
78 "/tmp/images/" +
79 boost::uuids::to_string(boost::uuids::random_generator()()));
80 CROW_LOG_DEBUG << "Writing file to " << filepath;
81 std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
82 std::ofstream::trunc);
83 out << req.body;
84 out.close();
85}
86
87template <typename... Middlewares>
88void requestRoutes(Crow<Middlewares...>& app) {
89 CROW_ROUTE(app, "/upload/image/<str>")
90 .methods("POST"_method,
91 "PUT"_method)([](const crow::request& req, crow::response& res,
92 const std::string& filename) {
93 uploadImageHandler(req, res, filename);
94 });
95
96 CROW_ROUTE(app, "/upload/image")
97 .methods("POST"_method,
98 "PUT"_method)([](const crow::request& req, crow::response& res) {
99 uploadImageHandler(req, res, "");
100 });
101}
102} // namespace image_upload
103} // namespace crow