aboutsummaryrefslogtreecommitdiff
path: root/libwebserv/binder_response.cc
blob: ddcffab8cd3a95d4a33f1ac8b53d49f936aa9b8e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// Copyright 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "libwebserv/binder_response.h"

#include <base/bind.h>
#include <brillo/bind_lambda.h>

#include <brillo/http/http_request.h>
#include <brillo/mime_utils.h>
#include <brillo/streams/file_stream.h>
#include <brillo/streams/stream_utils.h>

using std::pair;
using std::string;
using std::vector;

using android::sp;
using android::binder::Status;
using android::webservd::IHttpRequest;

namespace libwebserv {

BinderResponse::BinderResponse(const sp<IHttpRequest>& request)
    : request_(request) {}

void BinderResponse::AddHeaders(const vector<pair<string, string>>& headers) {
  headers_.insert(headers.begin(), headers.end());
}

void BinderResponse::Reply(int status_code,
                           brillo::StreamPtr data_stream,
                           const std::string& mime_type) {
  vector<string> headers;
  AddHeader(brillo::http::response_header::kContentType, mime_type);
  ScopedFd data_out;

  for (const auto& header : headers_) {
    headers.emplace_back(header.first);
    headers.emplace_back(header.second);
  }

  int64_t data_size = -1;
  if (data_stream->CanGetSize()) {
    data_size = data_stream->GetRemainingSize();
  }

  if (!request_->Respond(status_code, headers,
                         data_size, &data_out).isOk()) {
    LOG(WARNING) << "Could not communicate response to server.";
    return;
  }

  int dupfd = dup(data_out.get());
  auto dest_stream =
      brillo::FileStream::FromFileDescriptor(dupfd, true, nullptr);
  CHECK(dest_stream);
  // Dummy callbacks for success/error of data-copy operation. We ignore both
  // notifications here.
  auto on_success = [](brillo::StreamPtr, brillo::StreamPtr, uint64_t) {};
  auto on_error = [](brillo::StreamPtr, brillo::StreamPtr,
                     const brillo::Error*) {};
  brillo::stream_utils::CopyData(
      std::move(data_stream), std::move(dest_stream), base::Bind(on_success),
      base::Bind(on_error));
}

}  // namespace libwebserv