blob: df5c1ae491f63f4bf26fc131d82cd1c6bf8da5af [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
Ed Tanous55c7b7a2018-05-22 15:27:24 -070017inline void uploadImageHandler(const crow::Request& req, crow::Response& res,
Ed Tanousc3ee5222018-05-01 12:58:27 -070018 const std::string& filename) {
19 // Only allow one FW update at a time
20 if (fwUpdateMatcher != nullptr) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -070021 res.addHeader("Retry-After", "30");
Ed Tanousc3ee5222018-05-01 12:58:27 -070022 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
Ed Tanous55c7b7a2018-05-22 15:27:24 -070027 static boost::asio::deadline_timer timeout(*req.ioService,
Ed Tanousc3ee5222018-05-01 12:58:27 -070028 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 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -070038 BMCWEB_LOG_ERROR << "Timed out waiting for log event";
Ed Tanousc3ee5222018-05-01 12:58:27 -070039
40 if (ec) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -070041 BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
Ed Tanousc3ee5222018-05-01 12:58:27 -070042 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) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -070051 BMCWEB_LOG_DEBUG << "Match fired";
Ed Tanousc3ee5222018-05-01 12:58:27 -070052 boost::system::error_code ec;
53 timeout.cancel(ec);
54 if (ec) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -070055 BMCWEB_LOG_ERROR << "error canceling timer " << ec;
Ed Tanousc3ee5222018-05-01 12:58:27 -070056 }
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 }
Ed Tanous55c7b7a2018-05-22 15:27:24 -070064 res.jsonValue = {{"data", std::move(versionInfo)},
65 {"message", "200 OK"},
66 {"status", "ok"}};
67 BMCWEB_LOG_DEBUG << "ending response";
Ed Tanousc3ee5222018-05-01 12:58:27 -070068 res.end();
69 fwUpdateMatcher = nullptr;
70 };
71 fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
Ed Tanous55c7b7a2018-05-22 15:27:24 -070072 *crow::connections::systemBus,
Ed Tanousc3ee5222018-05-01 12:58:27 -070073 "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()()));
Ed Tanous55c7b7a2018-05-22 15:27:24 -070080 BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
Ed Tanousc3ee5222018-05-01 12:58:27 -070081 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) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -070089 BMCWEB_ROUTE(app, "/upload/image/<str>")
Ed Tanousc3ee5222018-05-01 12:58:27 -070090 .methods("POST"_method,
Ed Tanous55c7b7a2018-05-22 15:27:24 -070091 "PUT"_method)([](const crow::Request& req, crow::Response& res,
Ed Tanousc3ee5222018-05-01 12:58:27 -070092 const std::string& filename) {
93 uploadImageHandler(req, res, filename);
94 });
95
Ed Tanous55c7b7a2018-05-22 15:27:24 -070096 BMCWEB_ROUTE(app, "/upload/image")
Ed Tanousc3ee5222018-05-01 12:58:27 -070097 .methods("POST"_method,
Ed Tanous55c7b7a2018-05-22 15:27:24 -070098 "PUT"_method)([](const crow::Request& req, crow::Response& res) {
Ed Tanousc3ee5222018-05-01 12:58:27 -070099 uploadImageHandler(req, res, "");
100 });
101}
102} // namespace image_upload
103} // namespace crow