done:
const char* msg = wrap->callbacks()->Error();
- if (msg != nullptr)
+ if (msg != nullptr) {
req_wrap_obj->Set(env->error_string(), OneByteString(env->isolate(), msg));
+ wrap->callbacks()->ClearError();
+ }
req_wrap_obj->Set(env->bytes_string(),
Integer::NewFromUnsigned(env->isolate(), length));
args.GetReturnValue().Set(err);
done:
const char* msg = wrap->callbacks()->Error();
- if (msg != nullptr)
+ if (msg != nullptr) {
req_wrap_obj->Set(env->error_string(), OneByteString(env->isolate(), msg));
+ wrap->callbacks()->ClearError();
+ }
req_wrap_obj->Set(env->bytes_string(),
Integer::NewFromUnsigned(env->isolate(), data_size));
args.GetReturnValue().Set(err);
req_wrap->object()->Set(env->bytes_string(),
Number::New(env->isolate(), bytes));
const char* msg = wrap->callbacks()->Error();
- if (msg != nullptr)
+ if (msg != nullptr) {
req_wrap_obj->Set(env->error_string(), OneByteString(env->isolate(), msg));
+ wrap->callbacks()->ClearError();
+ }
if (err) {
req_wrap->~WriteWrap();
};
const char* msg = wrap->callbacks()->Error();
- if (msg != nullptr)
+ if (msg != nullptr) {
argv[3] = OneByteString(env->isolate(), msg);
+ wrap->callbacks()->ClearError();
+ }
req_wrap->MakeCallback(env->oncomplete_string(), ARRAY_SIZE(argv), argv);
}
-const char* StreamWrapCallbacks::Error() {
+const char* StreamWrapCallbacks::Error() const {
return nullptr;
}
+void StreamWrapCallbacks::ClearError() {
+}
+
+
// NOTE: Call to this function could change both `buf`'s and `count`'s
// values, shifting their base and decrementing their length. This is
// required in order to skip the data that was successfully written via
virtual ~StreamWrapCallbacks() = default;
- virtual const char* Error();
+ virtual const char* Error() const;
+ virtual void ClearError();
virtual int TryWrite(uv_buf_t** bufs, size_t* count);
using v8::String;
using v8::Value;
-size_t TLSCallbacks::error_off_;
-char TLSCallbacks::error_buf_[1024];
-
TLSCallbacks::TLSCallbacks(Environment* env,
Kind kind,
WriteItem* wi = ContainerOf(&WriteItem::member_, q);
delete wi;
}
+
+ ClearError();
}
}
-int TLSCallbacks::PrintErrorsCb(const char* str, size_t len, void* arg) {
- size_t to_copy = error_off_;
- size_t avail = sizeof(error_buf_) - error_off_ - 1;
-
- if (avail > to_copy)
- to_copy = avail;
-
- memcpy(error_buf_, str, avail);
- error_off_ += avail;
- CHECK_LT(error_off_, sizeof(error_buf_));
-
- // Zero-terminate
- error_buf_[error_off_] = '\0';
-
- return 0;
-}
-
-
-const char* TLSCallbacks::PrintErrors() {
- error_off_ = 0;
- ERR_print_errors_cb(PrintErrorsCb, this);
-
- return error_buf_;
-}
-
-
Local<Value> TLSCallbacks::GetSSLError(int status, int* err, const char** msg) {
EscapableHandleScope scope(env()->isolate());
{
CHECK(*err == SSL_ERROR_SSL || *err == SSL_ERROR_SYSCALL);
- const char* buf = PrintErrors();
+ BIO* bio = BIO_new(BIO_s_mem());
+ ERR_print_errors(bio);
+
+ BUF_MEM* mem;
+ BIO_get_mem_ptr(bio, &mem);
Local<String> message =
- OneByteString(env()->isolate(), buf, strlen(buf));
+ OneByteString(env()->isolate(), mem->data, mem->length);
Local<Value> exception = Exception::Error(message);
if (msg != nullptr) {
CHECK_EQ(*msg, nullptr);
+ char* const buf = new char[mem->length + 1];
+ memcpy(buf, mem->data, mem->length);
+ buf[mem->length] = '\0';
*msg = buf;
}
+ static_cast<void>(BIO_reset(bio));
return scope.Escape(exception);
}
if (!arg.IsEmpty()) {
MakePending();
if (!InvokeQueued(UV_EPROTO))
- error_ = nullptr;
+ ClearError();
clear_in_->Reset();
}
}
-const char* TLSCallbacks::Error() {
- const char* ret = error_;
+const char* TLSCallbacks::Error() const {
+ return error_;
+}
+
+
+void TLSCallbacks::ClearError() {
+ delete[] error_;
error_ = nullptr;
- return ret;
}
v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context);
- const char* Error() override;
+ const char* Error() const override;
+ void ClearError() override;
int TryWrite(uv_buf_t** bufs, size_t* count) override;
int DoWrite(WriteWrap* w,
uv_buf_t* bufs,
}
}
+ // If |msg| is not nullptr, caller is responsible for calling `delete[] *msg`.
v8::Local<v8::Value> GetSSLError(int status, int* err, const char** msg);
- const char* PrintErrors();
- static int PrintErrorsCb(const char* str, size_t len, void* arg);
static void OnClientHelloParseEnd(void* arg);
-
static void Wrap(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Receive(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
v8::Persistent<v8::Value> sni_context_;
#endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
-
- static size_t error_off_;
- static char error_buf_[1024];
};
} // namespace node