src: pass Isolate to all applicable api
[platform/upstream/nodejs.git] / src / udp_wrap.cc
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 #include "node.h"
23 #include "node_buffer.h"
24 #include "slab_allocator.h"
25 #include "req_wrap.h"
26 #include "handle_wrap.h"
27 #include "udp_wrap.h"
28
29 #include <stdlib.h>
30
31 #define SLAB_SIZE (1024 * 1024)
32
33
34 namespace node {
35
36 using v8::AccessorInfo;
37 using v8::Arguments;
38 using v8::Function;
39 using v8::FunctionTemplate;
40 using v8::Handle;
41 using v8::HandleScope;
42 using v8::Integer;
43 using v8::Local;
44 using v8::Object;
45 using v8::Persistent;
46 using v8::PropertyAttribute;
47 using v8::String;
48 using v8::Value;
49
50 typedef ReqWrap<uv_udp_send_t> SendWrap;
51
52 // see tcp_wrap.cc
53 Local<Object> AddressToJS(const sockaddr* addr);
54
55 static Persistent<Function> constructor;
56 static Persistent<String> buffer_sym;
57 static Persistent<String> oncomplete_sym;
58 static Persistent<String> onmessage_sym;
59 static SlabAllocator* slab_allocator;
60
61
62 static void DeleteSlabAllocator(void*) {
63   delete slab_allocator;
64   slab_allocator = NULL;
65 }
66
67
68 UDPWrap::UDPWrap(Handle<Object> object): HandleWrap(object,
69                                                     (uv_handle_t*)&handle_) {
70   int r = uv_udp_init(uv_default_loop(), &handle_);
71   assert(r == 0); // can't fail anyway
72   handle_.data = reinterpret_cast<void*>(this);
73 }
74
75
76 UDPWrap::~UDPWrap() {
77 }
78
79
80 void UDPWrap::Initialize(Handle<Object> target) {
81   HandleWrap::Initialize(target);
82
83   slab_allocator = new SlabAllocator(SLAB_SIZE);
84   AtExit(DeleteSlabAllocator, NULL);
85
86   HandleScope scope(node_isolate);
87
88   buffer_sym = NODE_PSYMBOL("buffer");
89   oncomplete_sym = NODE_PSYMBOL("oncomplete");
90   onmessage_sym = NODE_PSYMBOL("onmessage");
91
92   Local<FunctionTemplate> t = FunctionTemplate::New(New);
93   t->InstanceTemplate()->SetInternalFieldCount(1);
94   t->SetClassName(String::NewSymbol("UDP"));
95
96   enum PropertyAttribute attributes =
97       static_cast<PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
98   t->InstanceTemplate()->SetAccessor(String::New("fd"),
99                                      UDPWrap::GetFD,
100                                      NULL,
101                                      Handle<Value>(),
102                                      v8::DEFAULT,
103                                      attributes);
104
105   NODE_SET_PROTOTYPE_METHOD(t, "bind", Bind);
106   NODE_SET_PROTOTYPE_METHOD(t, "send", Send);
107   NODE_SET_PROTOTYPE_METHOD(t, "bind6", Bind6);
108   NODE_SET_PROTOTYPE_METHOD(t, "send6", Send6);
109   NODE_SET_PROTOTYPE_METHOD(t, "close", Close);
110   NODE_SET_PROTOTYPE_METHOD(t, "recvStart", RecvStart);
111   NODE_SET_PROTOTYPE_METHOD(t, "recvStop", RecvStop);
112   NODE_SET_PROTOTYPE_METHOD(t, "getsockname", GetSockName);
113   NODE_SET_PROTOTYPE_METHOD(t, "addMembership", AddMembership);
114   NODE_SET_PROTOTYPE_METHOD(t, "dropMembership", DropMembership);
115   NODE_SET_PROTOTYPE_METHOD(t, "setMulticastTTL", SetMulticastTTL);
116   NODE_SET_PROTOTYPE_METHOD(t, "setMulticastLoopback", SetMulticastLoopback);
117   NODE_SET_PROTOTYPE_METHOD(t, "setBroadcast", SetBroadcast);
118   NODE_SET_PROTOTYPE_METHOD(t, "setTTL", SetTTL);
119
120   NODE_SET_PROTOTYPE_METHOD(t, "ref", HandleWrap::Ref);
121   NODE_SET_PROTOTYPE_METHOD(t, "unref", HandleWrap::Unref);
122
123   constructor = Persistent<Function>::New(node_isolate,
124       Persistent<FunctionTemplate>::New(node_isolate, t)->GetFunction());
125   target->Set(String::NewSymbol("UDP"), constructor);
126 }
127
128
129 Handle<Value> UDPWrap::New(const Arguments& args) {
130   HandleScope scope(node_isolate);
131
132   assert(args.IsConstructCall());
133   new UDPWrap(args.This());
134
135   return scope.Close(args.This());
136 }
137
138
139 Handle<Value> UDPWrap::GetFD(Local<String>, const AccessorInfo& args) {
140 #if defined(_WIN32)
141   return v8::Null(node_isolate);
142 #else
143   HandleScope scope(node_isolate);
144   UNWRAP(UDPWrap)
145   int fd = (wrap == NULL) ? -1 : wrap->handle_.io_watcher.fd;
146   return scope.Close(Integer::New(fd, node_isolate));
147 #endif
148 }
149
150
151 Handle<Value> UDPWrap::DoBind(const Arguments& args, int family) {
152   HandleScope scope(node_isolate);
153   int r;
154
155   UNWRAP(UDPWrap)
156
157   // bind(ip, port, flags)
158   assert(args.Length() == 3);
159
160   String::Utf8Value address(args[0]);
161   const int port = args[1]->Uint32Value();
162   const int flags = args[2]->Uint32Value();
163
164   switch (family) {
165   case AF_INET:
166     r = uv_udp_bind(&wrap->handle_, uv_ip4_addr(*address, port), flags);
167     break;
168   case AF_INET6:
169     r = uv_udp_bind6(&wrap->handle_, uv_ip6_addr(*address, port), flags);
170     break;
171   default:
172     assert(0 && "unexpected address family");
173     abort();
174   }
175
176   if (r)
177     SetErrno(uv_last_error(uv_default_loop()));
178
179   return scope.Close(Integer::New(r, node_isolate));
180 }
181
182
183 Handle<Value> UDPWrap::Bind(const Arguments& args) {
184   return DoBind(args, AF_INET);
185 }
186
187
188 Handle<Value> UDPWrap::Bind6(const Arguments& args) {
189   return DoBind(args, AF_INET6);
190 }
191
192
193 #define X(name, fn)                                                           \
194   Handle<Value> UDPWrap::name(const Arguments& args) {                        \
195     HandleScope scope(node_isolate);                                          \
196     UNWRAP(UDPWrap)                                                           \
197     assert(args.Length() == 1);                                               \
198     int flag = args[0]->Int32Value();                                         \
199     int r = fn(&wrap->handle_, flag);                                         \
200     if (r) SetErrno(uv_last_error(uv_default_loop()));                        \
201     return scope.Close(Integer::New(r, node_isolate));                        \
202   }
203
204 X(SetTTL, uv_udp_set_ttl)
205 X(SetBroadcast, uv_udp_set_broadcast)
206 X(SetMulticastTTL, uv_udp_set_multicast_ttl)
207 X(SetMulticastLoopback, uv_udp_set_multicast_loop)
208
209 #undef X
210
211
212 Handle<Value> UDPWrap::SetMembership(const Arguments& args,
213                                      uv_membership membership) {
214   HandleScope scope(node_isolate);
215   UNWRAP(UDPWrap)
216
217   assert(args.Length() == 2);
218
219   String::Utf8Value address(args[0]);
220   String::Utf8Value iface(args[1]);
221
222   const char* iface_cstr = *iface;
223   if (args[1]->IsUndefined() || args[1]->IsNull()) {
224       iface_cstr = NULL;
225   }
226
227   int r = uv_udp_set_membership(&wrap->handle_, *address, iface_cstr,
228                                 membership);
229
230   if (r)
231     SetErrno(uv_last_error(uv_default_loop()));
232
233   return scope.Close(Integer::New(r, node_isolate));
234 }
235
236
237 Handle<Value> UDPWrap::AddMembership(const Arguments& args) {
238   return SetMembership(args, UV_JOIN_GROUP);
239 }
240
241
242 Handle<Value> UDPWrap::DropMembership(const Arguments& args) {
243   return SetMembership(args, UV_LEAVE_GROUP);
244 }
245
246
247 Handle<Value> UDPWrap::DoSend(const Arguments& args, int family) {
248   HandleScope scope(node_isolate);
249   int r;
250
251   // send(buffer, offset, length, port, address)
252   assert(args.Length() == 5);
253
254   UNWRAP(UDPWrap)
255
256   assert(Buffer::HasInstance(args[0]));
257   Local<Object> buffer_obj = args[0]->ToObject();
258
259   size_t offset = args[1]->Uint32Value();
260   size_t length = args[2]->Uint32Value();
261   assert(offset < Buffer::Length(buffer_obj));
262   assert(length <= Buffer::Length(buffer_obj) - offset);
263
264   SendWrap* req_wrap = new SendWrap();
265   req_wrap->object_->SetHiddenValue(buffer_sym, buffer_obj);
266
267   uv_buf_t buf = uv_buf_init(Buffer::Data(buffer_obj) + offset,
268                              length);
269
270   const unsigned short port = args[3]->Uint32Value();
271   String::Utf8Value address(args[4]);
272
273   switch (family) {
274   case AF_INET:
275     r = uv_udp_send(&req_wrap->req_, &wrap->handle_, &buf, 1,
276                     uv_ip4_addr(*address, port), OnSend);
277     break;
278   case AF_INET6:
279     r = uv_udp_send6(&req_wrap->req_, &wrap->handle_, &buf, 1,
280                      uv_ip6_addr(*address, port), OnSend);
281     break;
282   default:
283     assert(0 && "unexpected address family");
284     abort();
285   }
286
287   req_wrap->Dispatched();
288
289   if (r) {
290     SetErrno(uv_last_error(uv_default_loop()));
291     delete req_wrap;
292     return Null(node_isolate);
293   }
294   else {
295     return scope.Close(req_wrap->object_);
296   }
297 }
298
299
300 Handle<Value> UDPWrap::Send(const Arguments& args) {
301   return DoSend(args, AF_INET);
302 }
303
304
305 Handle<Value> UDPWrap::Send6(const Arguments& args) {
306   return DoSend(args, AF_INET6);
307 }
308
309
310 Handle<Value> UDPWrap::RecvStart(const Arguments& args) {
311   HandleScope scope(node_isolate);
312
313   UNWRAP(UDPWrap)
314
315   // UV_EALREADY means that the socket is already bound but that's okay
316   int r = uv_udp_recv_start(&wrap->handle_, OnAlloc, OnRecv);
317   if (r && uv_last_error(uv_default_loop()).code != UV_EALREADY) {
318     SetErrno(uv_last_error(uv_default_loop()));
319     return False(node_isolate);
320   }
321
322   return True(node_isolate);
323 }
324
325
326 Handle<Value> UDPWrap::RecvStop(const Arguments& args) {
327   HandleScope scope(node_isolate);
328
329   UNWRAP(UDPWrap)
330
331   int r = uv_udp_recv_stop(&wrap->handle_);
332
333   return scope.Close(Integer::New(r, node_isolate));
334 }
335
336
337 Handle<Value> UDPWrap::GetSockName(const Arguments& args) {
338   HandleScope scope(node_isolate);
339   struct sockaddr_storage address;
340
341   UNWRAP(UDPWrap)
342
343   int addrlen = sizeof(address);
344   int r = uv_udp_getsockname(&wrap->handle_,
345                              reinterpret_cast<sockaddr*>(&address),
346                              &addrlen);
347
348   if (r) {
349     SetErrno(uv_last_error(uv_default_loop()));
350     return Null(node_isolate);
351   }
352
353   const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
354   return scope.Close(AddressToJS(addr));
355 }
356
357
358 // TODO share with StreamWrap::AfterWrite() in stream_wrap.cc
359 void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
360   HandleScope scope(node_isolate);
361
362   assert(req != NULL);
363
364   SendWrap* req_wrap = reinterpret_cast<SendWrap*>(req->data);
365   UDPWrap* wrap = reinterpret_cast<UDPWrap*>(req->handle->data);
366
367   assert(req_wrap->object_.IsEmpty() == false);
368   assert(wrap->object_.IsEmpty() == false);
369
370   if (status) {
371     SetErrno(uv_last_error(uv_default_loop()));
372   }
373
374   Local<Value> argv[4] = {
375     Integer::New(status, node_isolate),
376     Local<Value>::New(node_isolate, wrap->object_),
377     Local<Value>::New(node_isolate, req_wrap->object_),
378     req_wrap->object_->GetHiddenValue(buffer_sym),
379   };
380
381   MakeCallback(req_wrap->object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
382   delete req_wrap;
383 }
384
385
386 uv_buf_t UDPWrap::OnAlloc(uv_handle_t* handle, size_t suggested_size) {
387   UDPWrap* wrap = static_cast<UDPWrap*>(handle->data);
388   char* buf = slab_allocator->Allocate(wrap->object_, suggested_size);
389   return uv_buf_init(buf, suggested_size);
390 }
391
392
393 void UDPWrap::OnRecv(uv_udp_t* handle,
394                      ssize_t nread,
395                      uv_buf_t buf,
396                      struct sockaddr* addr,
397                      unsigned flags) {
398   HandleScope scope(node_isolate);
399
400   UDPWrap* wrap = reinterpret_cast<UDPWrap*>(handle->data);
401   Local<Object> slab = slab_allocator->Shrink(wrap->object_,
402                                               buf.base,
403                                               nread < 0 ? 0 : nread);
404   if (nread == 0) return;
405
406   if (nread < 0) {
407     Local<Value> argv[] = { Local<Object>::New(node_isolate, wrap->object_) };
408     SetErrno(uv_last_error(uv_default_loop()));
409     MakeCallback(wrap->object_, onmessage_sym, ARRAY_SIZE(argv), argv);
410     return;
411   }
412
413   Local<Value> argv[] = {
414     Local<Object>::New(node_isolate, wrap->object_),
415     slab,
416     Integer::NewFromUnsigned(buf.base - Buffer::Data(slab), node_isolate),
417     Integer::NewFromUnsigned(nread, node_isolate),
418     AddressToJS(addr)
419   };
420   MakeCallback(wrap->object_, onmessage_sym, ARRAY_SIZE(argv), argv);
421 }
422
423
424 UDPWrap* UDPWrap::Unwrap(Local<Object> obj) {
425   assert(!obj.IsEmpty());
426   assert(obj->InternalFieldCount() > 0);
427   return static_cast<UDPWrap*>(obj->GetAlignedPointerFromInternalField(0));
428 }
429
430
431 Local<Object> UDPWrap::Instantiate() {
432   // If this assert fires then Initialize hasn't been called yet.
433   assert(constructor.IsEmpty() == false);
434
435   HandleScope scope(node_isolate);
436   Local<Object> obj = constructor->NewInstance();
437
438   return scope.Close(obj);
439 }
440
441
442 uv_udp_t* UDPWrap::UVHandle() {
443   return &handle_;
444 }
445
446
447 } // namespace node
448
449 NODE_MODULE(node_udp_wrap, node::UDPWrap::Initialize)