* Copyright 2022 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Niels Sascha Reedijk, niels.reedijk@gmail.com
*/
#ifndef _HTTP_RESULT_PRIVATE_H_
#define _HTTP_RESULT_PRIVATE_H_
#include <memory>
#include <optional>
#include <string>
#include <DataIO.h>
#include <ExclusiveBorrow.h>
#include <OS.h>
#include <String.h>
namespace BPrivate {
namespace Network {
struct HttpResultPrivate {
const int32 id;
enum { kNoData = 0, kStatusReady, kHeadersReady, kBodyReady, kError };
int32 requestStatus = kNoData;
int32 canCancel = 0;
sem_id data_wait;
std::optional<BHttpStatus> status;
std::optional<BHttpFields> fields;
std::optional<BHttpBody> body;
std::optional<std::exception_ptr> error;
BString bodyString;
BBorrow<BDataIO> bodyTarget;
HttpResultPrivate(int32 identifier);
int32 GetStatusAtomic();
bool CanCancel();
void SetCancel();
void SetError(std::exception_ptr e);
void SetStatus(BHttpStatus&& s);
void SetFields(BHttpFields&& f);
void SetBody();
size_t WriteToBody(const void* buffer, size_t size);
};
inline HttpResultPrivate::HttpResultPrivate(int32 identifier)
:
id(identifier)
{
std::string name = "httpresult:" + std::to_string(identifier);
data_wait = create_sem(1, name.c_str());
if (data_wait < B_OK)
throw BRuntimeError(__PRETTY_FUNCTION__, "Cannot create internal sem for httpresult");
}
inline int32
HttpResultPrivate::GetStatusAtomic()
{
return atomic_get(&requestStatus);
}
inline bool
HttpResultPrivate::CanCancel()
{
return atomic_get(&canCancel) == 1;
}
inline void
HttpResultPrivate::SetCancel()
{
atomic_set(&canCancel, 1);
}
inline void
HttpResultPrivate::SetError(std::exception_ptr e)
{
bodyTarget.Return();
error = e;
atomic_set(&requestStatus, kError);
release_sem(data_wait);
}
inline void
HttpResultPrivate::SetStatus(BHttpStatus&& s)
{
status = std::move(s);
atomic_set(&requestStatus, kStatusReady);
release_sem(data_wait);
}
inline void
HttpResultPrivate::SetFields(BHttpFields&& f)
{
fields = std::move(f);
atomic_set(&requestStatus, kHeadersReady);
release_sem(data_wait);
}
inline void
HttpResultPrivate::SetBody()
{
if (bodyTarget.HasValue()) {
body = BHttpBody{};
bodyTarget.Return();
} else
body = BHttpBody{std::move(bodyString)};
atomic_set(&requestStatus, kBodyReady);
release_sem(data_wait);
}
inline size_t
HttpResultPrivate::WriteToBody(const void* buffer, size_t size)
{
if (bodyTarget.HasValue()) {
auto result = bodyTarget->Write(buffer, size);
if (result < 0)
throw BSystemError("BDataIO::Write()", result);
return result;
} else {
bodyString.Append(reinterpret_cast<const char*>(buffer), size);
return size;
}
}
}
}
#endif