%PDF- %PDF-
| Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/src/quic/ |
| Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/src/quic/logstream.cc |
#if HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC
#include "logstream.h"
#include <async_wrap-inl.h>
#include <base_object-inl.h>
#include <env-inl.h>
#include <memory_tracker-inl.h>
#include <node_external_reference.h>
#include <stream_base-inl.h>
#include <uv.h>
#include <v8.h>
#include "bindingdata.h"
namespace node {
using v8::FunctionTemplate;
using v8::Local;
using v8::Object;
namespace quic {
Local<FunctionTemplate> LogStream::GetConstructorTemplate(Environment* env) {
auto& state = BindingData::Get(env);
auto tmpl = state.logstream_constructor_template();
if (tmpl.IsEmpty()) {
tmpl = FunctionTemplate::New(env->isolate());
tmpl->Inherit(AsyncWrap::GetConstructorTemplate(env));
tmpl->InstanceTemplate()->SetInternalFieldCount(
StreamBase::kInternalFieldCount);
tmpl->SetClassName(state.logstream_string());
StreamBase::AddMethods(env, tmpl);
state.set_logstream_constructor_template(tmpl);
}
return tmpl;
}
BaseObjectPtr<LogStream> LogStream::Create(Environment* env) {
v8::Local<v8::Object> obj;
if (!GetConstructorTemplate(env)
->InstanceTemplate()
->NewInstance(env->context())
.ToLocal(&obj)) {
return BaseObjectPtr<LogStream>();
}
return MakeDetachedBaseObject<LogStream>(env, obj);
}
LogStream::LogStream(Environment* env, Local<Object> obj)
: AsyncWrap(env, obj, AsyncWrap::PROVIDER_QUIC_LOGSTREAM), StreamBase(env) {
MakeWeak();
StreamBase::AttachToObject(GetObject());
}
void LogStream::Emit(const uint8_t* data, size_t len, EmitOption option) {
if (fin_seen_) return;
fin_seen_ = option == EmitOption::FIN;
size_t remaining = len;
// If the len is greater than the size of the buffer returned by
// EmitAlloc then EmitRead will be called multiple times.
while (remaining != 0) {
uv_buf_t buf = EmitAlloc(len);
size_t len = std::min<size_t>(remaining, buf.len);
memcpy(buf.base, data, len);
remaining -= len;
data += len;
// If we are actively reading from the stream, we'll call emit
// read immediately. Otherwise we buffer the chunk and will push
// the chunks out the next time ReadStart() is called.
if (reading_) {
EmitRead(len, buf);
} else {
// The total measures the total memory used so we always
// increment but buf.len and not chunk len.
ensure_space(buf.len);
total_ += buf.len;
buffer_.push_back(Chunk{len, buf});
}
}
if (ended_ && reading_) {
EmitRead(UV_EOF);
}
}
void LogStream::Emit(const std::string_view line, EmitOption option) {
Emit(reinterpret_cast<const uint8_t*>(line.data()), line.length(), option);
}
void LogStream::End() {
ended_ = true;
}
int LogStream::ReadStart() {
if (reading_) return 0;
// Flush any chunks that have already been buffered.
for (const auto& chunk : buffer_) EmitRead(chunk.len, chunk.buf);
total_ = 0;
buffer_.clear();
if (fin_seen_) {
// If we've already received the fin, there's nothing else to wait for.
EmitRead(UV_EOF);
return ReadStop();
}
// Otherwise, we're going to wait for more chunks to be written.
reading_ = true;
return 0;
}
int LogStream::ReadStop() {
reading_ = false;
return 0;
}
// We do not use either of these.
int LogStream::DoShutdown(ShutdownWrap* req_wrap) {
UNREACHABLE();
}
int LogStream::DoWrite(WriteWrap* w,
uv_buf_t* bufs,
size_t count,
uv_stream_t* send_handle) {
UNREACHABLE();
}
bool LogStream::IsAlive() {
return !ended_;
}
bool LogStream::IsClosing() {
return ended_;
}
AsyncWrap* LogStream::GetAsyncWrap() {
return this;
}
void LogStream::MemoryInfo(MemoryTracker* tracker) const {
tracker->TrackFieldWithSize("buffer", total_);
}
// The LogStream buffer enforces a maximum size of kMaxLogStreamBuffer.
void LogStream::ensure_space(size_t amt) {
while (total_ + amt > kMaxLogStreamBuffer) {
total_ -= buffer_.front().buf.len;
buffer_.pop_front();
}
}
} // namespace quic
} // namespace node
#endif // HAVE_OPENSSL && NODE_OPENSSL_HAS_QUIC