diff --git a/lib/dgram.js b/lib/dgram.js index 72959f5abd..743dc9abcd 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -343,16 +343,11 @@ Socket.prototype._stopReceiving = function() { }; -function onMessage(handle, nread, buf, rinfo) { +function onMessage(handle, slab, start, len, rinfo) { var self = handle.socket; - - if (nread == -1) { - self.emit('error', errnoException(errno, 'recvmsg')); - } - else { - rinfo.size = buf.length; // compatibility - self.emit('message', buf, rinfo); - } + if (!slab) return self.emit('error', errnoException(errno, 'recvmsg')); + rinfo.size = len; // compatibility + self.emit('message', slab.slice(start, start + len), rinfo); } diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index 6cb2bb65bb..8d491bb1ac 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -21,12 +21,14 @@ #include "node.h" #include "node_buffer.h" - +#include "slab_allocator.h" #include "req_wrap.h" #include "handle_wrap.h" #include +#define SLAB_SIZE (1024 * 1024) + // Temporary hack: libuv should provide uv_inet_pton and uv_inet_ntop. // Clean this up in tcp_wrap.cc too. #if defined(__MINGW32__) || defined(_MSC_VER) @@ -59,16 +61,17 @@ namespace node { return scope.Close(Integer::New(-1)); \ } -// TODO share with tcp_wrap.cc -Persistent address_symbol; -Persistent port_symbol; -Persistent buffer_sym; +typedef ReqWrap SendWrap; void AddressToJS(Handle info, const sockaddr* addr, int addrlen); -typedef ReqWrap SendWrap; + +static Persistent address_symbol; +static Persistent port_symbol; +static Persistent buffer_sym; +static SlabAllocator slab_allocator(SLAB_SIZE); class UDPWrap: public HandleWrap { @@ -402,7 +405,9 @@ void UDPWrap::OnSend(uv_udp_send_t* req, int status) { uv_buf_t UDPWrap::OnAlloc(uv_handle_t* handle, size_t suggested_size) { - return uv_buf_init(new char[suggested_size], suggested_size); + UDPWrap* wrap = static_cast(handle->data); + char* buf = slab_allocator.Allocate(wrap->object_, suggested_size); + return uv_buf_init(buf, suggested_size); } @@ -413,32 +418,29 @@ void UDPWrap::OnRecv(uv_udp_t* handle, unsigned flags) { HandleScope scope; - if (nread == 0) { - free(buf.base); + UDPWrap* wrap = reinterpret_cast(handle->data); + Local slab = slab_allocator.Shrink(wrap->object_, + buf.base, + nread < 0 ? 0 : nread); + if (nread == 0) return; + + if (nread < 0) { + Local argv[] = { Local::New(wrap->object_) }; + SetErrno(uv_last_error(uv_default_loop())); + MakeCallback(wrap->object_, "onmessage", ARRAY_SIZE(argv), argv); return; } - UDPWrap* wrap = reinterpret_cast(handle->data); + Local rinfo = Object::New(); + AddressToJS(rinfo, addr, sizeof(*addr)); - Local argv[4] = { + Local argv[] = { Local::New(wrap->object_), - Integer::New(nread), - Local::New(Null()), - Local::New(Null()) + slab, + Integer::NewFromUnsigned(buf.base - Buffer::Data(slab)), + Integer::NewFromUnsigned(nread), + rinfo }; - - if (nread == -1) { - SetErrno(uv_last_error(uv_default_loop())); - } - else { - Local rinfo = Object::New(); - AddressToJS(rinfo, addr, sizeof *addr); - argv[2] = Local::New( - Buffer::New(buf.base, nread, NULL, NULL)->handle_); - argv[3] = rinfo; - } - free(buf.base); - MakeCallback(wrap->object_, "onmessage", ARRAY_SIZE(argv), argv); }