diff options
author | Matteo Collina <hello@matteocollina.com> | 2016-01-29 14:18:27 +0100 |
---|---|---|
committer | Matteo Collina <hello@matteocollina.com> | 2016-01-29 19:26:44 +0100 |
commit | 137f53c7b72ff9cb36694d058136344076661f4a (patch) | |
tree | b5dd2bad2463b37ff541726ad1f272e21920f212 /src/udp_wrap.cc | |
parent | 4126441013bb569c19417f4a23c5f6b3bc38ef2b (diff) | |
download | android-node-v8-137f53c7b72ff9cb36694d058136344076661f4a.tar.gz android-node-v8-137f53c7b72ff9cb36694d058136344076661f4a.tar.bz2 android-node-v8-137f53c7b72ff9cb36694d058136344076661f4a.zip |
dgram: support dgram.send with multiple buffers
Added ability to dgram.send to send multiple buffers, _writev style.
The offset and length parameters in dgram.send are now optional.
Refactored the dgram benchmarks, and seperated them from net.
Added docs for the new signature.
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
Fixes: https://github.com/nodejs/node/issues/4302
PR-URL: https://github.com/nodejs/node/pull/4374
Diffstat (limited to 'src/udp_wrap.cc')
-rw-r--r-- | src/udp_wrap.cc | 64 |
1 files changed, 45 insertions, 19 deletions
diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index cb678f14fb..1faf45a95d 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -13,6 +13,7 @@ namespace node { +using v8::Array; using v8::Context; using v8::EscapableHandleScope; using v8::External; @@ -35,6 +36,7 @@ class SendWrap : public ReqWrap<uv_udp_send_t> { public: SendWrap(Environment* env, Local<Object> req_wrap_obj, bool have_callback); inline bool have_callback() const; + size_t msg_size; size_t self_size() const override { return sizeof(*this); } private: const bool have_callback_; @@ -243,29 +245,46 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) { UDPWrap* wrap = Unwrap<UDPWrap>(args.Holder()); - // send(req, buffer, offset, length, port, address) + // send(req, buffer, port, address, hasCallback) CHECK(args[0]->IsObject()); - CHECK(Buffer::HasInstance(args[1])); + CHECK(args[1]->IsArray()); CHECK(args[2]->IsUint32()); CHECK(args[3]->IsUint32()); - CHECK(args[4]->IsUint32()); - CHECK(args[5]->IsString()); - CHECK(args[6]->IsBoolean()); + CHECK(args[4]->IsString()); + CHECK(args[5]->IsBoolean()); Local<Object> req_wrap_obj = args[0].As<Object>(); - Local<Object> buffer_obj = args[1].As<Object>(); - size_t offset = args[2]->Uint32Value(); - size_t length = args[3]->Uint32Value(); - const unsigned short port = args[4]->Uint32Value(); - node::Utf8Value address(env->isolate(), args[5]); - const bool have_callback = args[6]->IsTrue(); - - CHECK_LE(length, Buffer::Length(buffer_obj) - offset); + Local<Array> chunks = args[1].As<Array>(); + // it is faster to fetch the length of the + // array in js-land + size_t count = args[2]->Uint32Value(); + const unsigned short port = args[3]->Uint32Value(); + node::Utf8Value address(env->isolate(), args[4]); + const bool have_callback = args[5]->IsTrue(); SendWrap* req_wrap = new SendWrap(env, req_wrap_obj, have_callback); + size_t msg_size = 0; + + // allocate uv_buf_t of the correct size + // if bigger than 16 elements + uv_buf_t bufs_[16]; + uv_buf_t* bufs = bufs_; + + if (ARRAY_SIZE(bufs_) < count) + bufs = new uv_buf_t[count]; + + // construct uv_buf_t array + for (size_t i = 0; i < count; i++) { + Local<Value> chunk = chunks->Get(i); + + size_t length = Buffer::Length(chunk); + + bufs[i] = uv_buf_init(Buffer::Data(chunk), length); + msg_size += length; + } + + req_wrap->msg_size = msg_size; - uv_buf_t buf = uv_buf_init(Buffer::Data(buffer_obj) + offset, - length); char addr[sizeof(sockaddr_in6)]; int err; @@ -284,12 +303,16 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) { if (err == 0) { err = uv_udp_send(&req_wrap->req_, &wrap->handle_, - &buf, - 1, + bufs, + count, reinterpret_cast<const sockaddr*>(&addr), OnSend); } + // Deallocate space + if (bufs != bufs_) + delete[] bufs; + req_wrap->Dispatched(); if (err) delete req_wrap; @@ -332,8 +355,11 @@ void UDPWrap::OnSend(uv_udp_send_t* req, int status) { Environment* env = req_wrap->env(); HandleScope handle_scope(env->isolate()); Context::Scope context_scope(env->context()); - Local<Value> arg = Integer::New(env->isolate(), status); - req_wrap->MakeCallback(env->oncomplete_string(), 1, &arg); + Local<Value> arg[] = { + Integer::New(env->isolate(), status), + Integer::New(env->isolate(), req_wrap->msg_size), + }; + req_wrap->MakeCallback(env->oncomplete_string(), 2, arg); } delete req_wrap; } |