%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