summaryrefslogtreecommitdiff
path: root/src/udp_wrap.cc
diff options
context:
space:
mode:
authorMatteo Collina <hello@matteocollina.com>2016-01-29 14:18:27 +0100
committerMatteo Collina <hello@matteocollina.com>2016-01-29 19:26:44 +0100
commit137f53c7b72ff9cb36694d058136344076661f4a (patch)
treeb5dd2bad2463b37ff541726ad1f272e21920f212 /src/udp_wrap.cc
parent4126441013bb569c19417f4a23c5f6b3bc38ef2b (diff)
downloadandroid-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.cc64
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;
}