The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / src / udp_wrap.cc @ 0544a586

History | View | Annotate | Download (11.3 KB)

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
// Temporary hack: libuv should provide uv_inet_pton and uv_inet_ntop.
34
// Clean this up in tcp_wrap.cc too.
35
#if defined(__MINGW32__) || defined(_MSC_VER)
36
  extern "C" {
37
#   include <inet_net_pton.h>
38
#   include <inet_ntop.h>
39
  }
40
# define uv_inet_pton ares_inet_pton
41
# define uv_inet_ntop ares_inet_ntop
42

    
43
#else // __POSIX__
44
# include <arpa/inet.h>
45
# define uv_inet_pton inet_pton
46
# define uv_inet_ntop inet_ntop
47
#endif
48

    
49
using namespace v8;
50

    
51
namespace node {
52

    
53
typedef ReqWrap<uv_udp_send_t> SendWrap;
54

    
55
// see tcp_wrap.cc
56
Local<Object> AddressToJS(const sockaddr* addr);
57

    
58
static Persistent<String> buffer_sym;
59
static Persistent<String> oncomplete_sym;
60
static Persistent<String> onmessage_sym;
61
static SlabAllocator* slab_allocator;
62

    
63

    
64
static void DeleteSlabAllocator(void*) {
65
  delete slab_allocator;
66
  slab_allocator = NULL;
67
}
68

    
69

    
70
UDPWrap::UDPWrap(Handle<Object> object): HandleWrap(object,
71
                                                    (uv_handle_t*)&handle_) {
72
  int r = uv_udp_init(uv_default_loop(), &handle_);
73
  assert(r == 0); // can't fail anyway
74
  handle_.data = reinterpret_cast<void*>(this);
75
}
76

    
77

    
78
UDPWrap::~UDPWrap() {
79
}
80

    
81

    
82
void UDPWrap::Initialize(Handle<Object> target) {
83
  HandleWrap::Initialize(target);
84

    
85
  slab_allocator = new SlabAllocator(SLAB_SIZE);
86
  AtExit(DeleteSlabAllocator, NULL);
87

    
88
  HandleScope scope;
89

    
90
  buffer_sym = NODE_PSYMBOL("buffer");
91
  oncomplete_sym = NODE_PSYMBOL("oncomplete");
92
  onmessage_sym = NODE_PSYMBOL("onmessage");
93

    
94
  Local<FunctionTemplate> t = FunctionTemplate::New(New);
95
  t->InstanceTemplate()->SetInternalFieldCount(1);
96
  t->SetClassName(String::NewSymbol("UDP"));
97

    
98
  NODE_SET_PROTOTYPE_METHOD(t, "bind", Bind);
99
  NODE_SET_PROTOTYPE_METHOD(t, "send", Send);
100
  NODE_SET_PROTOTYPE_METHOD(t, "bind6", Bind6);
101
  NODE_SET_PROTOTYPE_METHOD(t, "send6", Send6);
102
  NODE_SET_PROTOTYPE_METHOD(t, "close", Close);
103
  NODE_SET_PROTOTYPE_METHOD(t, "recvStart", RecvStart);
104
  NODE_SET_PROTOTYPE_METHOD(t, "recvStop", RecvStop);
105
  NODE_SET_PROTOTYPE_METHOD(t, "getsockname", GetSockName);
106
  NODE_SET_PROTOTYPE_METHOD(t, "addMembership", AddMembership);
107
  NODE_SET_PROTOTYPE_METHOD(t, "dropMembership", DropMembership);
108
  NODE_SET_PROTOTYPE_METHOD(t, "setMulticastTTL", SetMulticastTTL);
109
  NODE_SET_PROTOTYPE_METHOD(t, "setMulticastLoopback", SetMulticastLoopback);
110
  NODE_SET_PROTOTYPE_METHOD(t, "setBroadcast", SetBroadcast);
111
  NODE_SET_PROTOTYPE_METHOD(t, "setTTL", SetTTL);
112

    
113
  target->Set(String::NewSymbol("UDP"),
114
              Persistent<FunctionTemplate>::New(t)->GetFunction());
115
}
116

    
117

    
118
Handle<Value> UDPWrap::New(const Arguments& args) {
119
  HandleScope scope;
120

    
121
  assert(args.IsConstructCall());
122
  new UDPWrap(args.This());
123

    
124
  return scope.Close(args.This());
125
}
126

    
127
Handle<Value> UDPWrap::DoBind(const Arguments& args, int family) {
128
  HandleScope scope;
129
  int r;
130

    
131
  UNWRAP(UDPWrap)
132

    
133
  // bind(ip, port, flags)
134
  assert(args.Length() == 3);
135

    
136
  String::Utf8Value address(args[0]);
137
  const int port = args[1]->Uint32Value();
138
  const int flags = args[2]->Uint32Value();
139

    
140
  switch (family) {
141
  case AF_INET:
142
    r = uv_udp_bind(&wrap->handle_, uv_ip4_addr(*address, port), flags);
143
    break;
144
  case AF_INET6:
145
    r = uv_udp_bind6(&wrap->handle_, uv_ip6_addr(*address, port), flags);
146
    break;
147
  default:
148
    assert(0 && "unexpected address family");
149
    abort();
150
  }
151

    
152
  if (r)
153
    SetErrno(uv_last_error(uv_default_loop()));
154

    
155
  return scope.Close(Integer::New(r));
156
}
157

    
158

    
159
Handle<Value> UDPWrap::Bind(const Arguments& args) {
160
  return DoBind(args, AF_INET);
161
}
162

    
163

    
164
Handle<Value> UDPWrap::Bind6(const Arguments& args) {
165
  return DoBind(args, AF_INET6);
166
}
167

    
168

    
169
#define X(name, fn)                                                           \
170
  Handle<Value> UDPWrap::name(const Arguments& args) {                        \
171
    HandleScope scope;                                                        \
172
    UNWRAP(UDPWrap)                                                                    \
173
    assert(args.Length() == 1);                                               \
174
    int flag = args[0]->Int32Value();                                         \
175
    int r = fn(&wrap->handle_, flag);                                         \
176
    if (r) SetErrno(uv_last_error(uv_default_loop()));                        \
177
    return scope.Close(Integer::New(r));                                      \
178
  }
179

    
180
X(SetTTL, uv_udp_set_ttl)
181
X(SetBroadcast, uv_udp_set_broadcast)
182
X(SetMulticastTTL, uv_udp_set_multicast_ttl)
183
X(SetMulticastLoopback, uv_udp_set_multicast_loop)
184

    
185
#undef X
186

    
187

    
188
Handle<Value> UDPWrap::SetMembership(const Arguments& args,
189
                                     uv_membership membership) {
190
  HandleScope scope;
191
  UNWRAP(UDPWrap)
192

    
193
  assert(args.Length() == 2);
194

    
195
  String::Utf8Value address(args[0]);
196
  String::Utf8Value iface(args[1]);
197

    
198
  const char* iface_cstr = *iface;
199
  if (args[1]->IsUndefined() || args[1]->IsNull()) {
200
      iface_cstr = NULL;
201
  }
202

    
203
  int r = uv_udp_set_membership(&wrap->handle_, *address, iface_cstr,
204
                                membership);
205

    
206
  if (r)
207
    SetErrno(uv_last_error(uv_default_loop()));
208

    
209
  return scope.Close(Integer::New(r));
210
}
211

    
212

    
213
Handle<Value> UDPWrap::AddMembership(const Arguments& args) {
214
  return SetMembership(args, UV_JOIN_GROUP);
215
}
216

    
217

    
218
Handle<Value> UDPWrap::DropMembership(const Arguments& args) {
219
  return SetMembership(args, UV_LEAVE_GROUP);
220
}
221

    
222

    
223
Handle<Value> UDPWrap::DoSend(const Arguments& args, int family) {
224
  HandleScope scope;
225
  int r;
226

    
227
  // send(buffer, offset, length, port, address)
228
  assert(args.Length() == 5);
229

    
230
  UNWRAP(UDPWrap)
231

    
232
  assert(Buffer::HasInstance(args[0]));
233
  Local<Object> buffer_obj = args[0]->ToObject();
234

    
235
  size_t offset = args[1]->Uint32Value();
236
  size_t length = args[2]->Uint32Value();
237
  assert(offset < Buffer::Length(buffer_obj));
238
  assert(length <= Buffer::Length(buffer_obj) - offset);
239

    
240
  SendWrap* req_wrap = new SendWrap();
241
  req_wrap->object_->SetHiddenValue(buffer_sym, buffer_obj);
242

    
243
  uv_buf_t buf = uv_buf_init(Buffer::Data(buffer_obj) + offset,
244
                             length);
245

    
246
  const unsigned short port = args[3]->Uint32Value();
247
  String::Utf8Value address(args[4]);
248

    
249
  switch (family) {
250
  case AF_INET:
251
    r = uv_udp_send(&req_wrap->req_, &wrap->handle_, &buf, 1,
252
                    uv_ip4_addr(*address, port), OnSend);
253
    break;
254
  case AF_INET6:
255
    r = uv_udp_send6(&req_wrap->req_, &wrap->handle_, &buf, 1,
256
                     uv_ip6_addr(*address, port), OnSend);
257
    break;
258
  default:
259
    assert(0 && "unexpected address family");
260
    abort();
261
  }
262

    
263
  req_wrap->Dispatched();
264

    
265
  if (r) {
266
    SetErrno(uv_last_error(uv_default_loop()));
267
    delete req_wrap;
268
    return Null();
269
  }
270
  else {
271
    return scope.Close(req_wrap->object_);
272
  }
273
}
274

    
275

    
276
Handle<Value> UDPWrap::Send(const Arguments& args) {
277
  return DoSend(args, AF_INET);
278
}
279

    
280

    
281
Handle<Value> UDPWrap::Send6(const Arguments& args) {
282
  return DoSend(args, AF_INET6);
283
}
284

    
285

    
286
Handle<Value> UDPWrap::RecvStart(const Arguments& args) {
287
  HandleScope scope;
288

    
289
  UNWRAP(UDPWrap)
290

    
291
  // UV_EALREADY means that the socket is already bound but that's okay
292
  int r = uv_udp_recv_start(&wrap->handle_, OnAlloc, OnRecv);
293
  if (r && uv_last_error(uv_default_loop()).code != UV_EALREADY) {
294
    SetErrno(uv_last_error(uv_default_loop()));
295
    return False();
296
  }
297

    
298
  return True();
299
}
300

    
301

    
302
Handle<Value> UDPWrap::RecvStop(const Arguments& args) {
303
  HandleScope scope;
304

    
305
  UNWRAP(UDPWrap)
306

    
307
  int r = uv_udp_recv_stop(&wrap->handle_);
308

    
309
  return scope.Close(Integer::New(r));
310
}
311

    
312

    
313
Handle<Value> UDPWrap::GetSockName(const Arguments& args) {
314
  HandleScope scope;
315
  struct sockaddr_storage address;
316

    
317
  UNWRAP(UDPWrap)
318

    
319
  int addrlen = sizeof(address);
320
  int r = uv_udp_getsockname(&wrap->handle_,
321
                             reinterpret_cast<sockaddr*>(&address),
322
                             &addrlen);
323

    
324
  if (r) {
325
    SetErrno(uv_last_error(uv_default_loop()));
326
    return Null();
327
  }
328

    
329
  const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
330
  return scope.Close(AddressToJS(addr));
331
}
332

    
333

    
334
// TODO share with StreamWrap::AfterWrite() in stream_wrap.cc
335
void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
336
  HandleScope scope;
337

    
338
  assert(req != NULL);
339

    
340
  SendWrap* req_wrap = reinterpret_cast<SendWrap*>(req->data);
341
  UDPWrap* wrap = reinterpret_cast<UDPWrap*>(req->handle->data);
342

    
343
  assert(req_wrap->object_.IsEmpty() == false);
344
  assert(wrap->object_.IsEmpty() == false);
345

    
346
  if (status) {
347
    SetErrno(uv_last_error(uv_default_loop()));
348
  }
349

    
350
  Local<Value> argv[4] = {
351
    Integer::New(status),
352
    Local<Value>::New(wrap->object_),
353
    Local<Value>::New(req_wrap->object_),
354
    req_wrap->object_->GetHiddenValue(buffer_sym),
355
  };
356

    
357
  MakeCallback(req_wrap->object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
358
  delete req_wrap;
359
}
360

    
361

    
362
uv_buf_t UDPWrap::OnAlloc(uv_handle_t* handle, size_t suggested_size) {
363
  UDPWrap* wrap = static_cast<UDPWrap*>(handle->data);
364
  char* buf = slab_allocator->Allocate(wrap->object_, suggested_size);
365
  return uv_buf_init(buf, suggested_size);
366
}
367

    
368

    
369
void UDPWrap::OnRecv(uv_udp_t* handle,
370
                     ssize_t nread,
371
                     uv_buf_t buf,
372
                     struct sockaddr* addr,
373
                     unsigned flags) {
374
  HandleScope scope;
375

    
376
  UDPWrap* wrap = reinterpret_cast<UDPWrap*>(handle->data);
377
  Local<Object> slab = slab_allocator->Shrink(wrap->object_,
378
                                              buf.base,
379
                                              nread < 0 ? 0 : nread);
380
  if (nread == 0) return;
381

    
382
  if (nread < 0) {
383
    Local<Value> argv[] = { Local<Object>::New(wrap->object_) };
384
    SetErrno(uv_last_error(uv_default_loop()));
385
    MakeCallback(wrap->object_, onmessage_sym, ARRAY_SIZE(argv), argv);
386
    return;
387
  }
388

    
389
  Local<Value> argv[] = {
390
    Local<Object>::New(wrap->object_),
391
    slab,
392
    Integer::NewFromUnsigned(buf.base - Buffer::Data(slab)),
393
    Integer::NewFromUnsigned(nread),
394
    AddressToJS(addr)
395
  };
396
  MakeCallback(wrap->object_, onmessage_sym, ARRAY_SIZE(argv), argv);
397
}
398

    
399

    
400
UDPWrap* UDPWrap::Unwrap(Local<Object> obj) {
401
  assert(!obj.IsEmpty());
402
  assert(obj->InternalFieldCount() > 0);
403
  return static_cast<UDPWrap*>(obj->GetPointerFromInternalField(0));
404
}
405

    
406

    
407
uv_udp_t* UDPWrap::UVHandle() {
408
  return &handle_;
409
}
410

    
411

    
412
} // namespace node
413

    
414
NODE_MODULE(node_udp_wrap, node::UDPWrap::Initialize)