blob: 4b7d1ea41eee484063ab5196606bf3c9306f73b6 [file] [log] [blame]
// 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 <errno.h>
#include <unistd.h>
#include <tuple>
#include "binder_request.h"
using android::status_t;
using android::Parcel;
using android::binder::Status;
using std::map;
using std::string;
using std::vector;
using std::tuple;
namespace android {
namespace webservd {
namespace {
Status DupToScopedFd(int fd, android::base::unique_fd* target) {
do {
target->reset(dup(fd));
} while (target->get() < 0 && (errno == EINTR || errno == EBUSY));
if (target->get() < 0) {
// Too many file descriptors open, or we had a bad file descriptor for this
// request for some reason
return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
}
return Status::ok();
}
} // namespace
Status HttpRequest::GetBody(android::base::unique_fd* body) {
return DupToScopedFd(request_->GetBodyDataFileDescriptor(), body);
}
Status HttpRequest::GetUrl(string* url) {
*url = request_->GetURL();
return Status::ok();
}
Status HttpRequest::GetMethod(string* method) {
*method = request_->GetMethod();
return Status::ok();
}
Status HttpRequest::GetQueryParams(vector<string>* params) {
for (const auto& it : request_->GetDataGet()) {
params->push_back(it.first);
params->push_back(it.second);
}
return Status::ok();
}
Status HttpRequest::GetPostParams(vector<string>* params) {
for (const auto& it : request_->GetDataPost()) {
params->push_back(it.first);
params->push_back(it.second);
}
return Status::ok();
}
Status HttpRequest::GetHeaders(vector<string>* headers) {
for (const auto& it : request_->GetHeaders()) {
headers->push_back(it.first);
headers->push_back(it.second);
}
return Status::ok();
}
Status HttpRequest::Respond(int32_t status_code,
const vector<string>& response_headers,
int32_t data_size,
android::base::unique_fd* response_stream) {
if (response_headers.size() % 2) {
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
String8("Header array contained unmatched key."));
}
vector<tuple<string,string>> headers_map;
for (auto it = response_headers.crbegin();
it != response_headers.crend() && it + 1 != response_headers.crend();
it += 2) {
headers_map.emplace_back(*it, *(it + 1));
}
::base::File file = request_->Complete(status_code, headers_map, data_size);
if (!file.IsValid()) {
// We've already handled this request
return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
}
response_stream->reset(file.TakePlatformFile());
return Status::ok();
}
} // namespace webservd
} // namespace android