Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 518 lines (391 sloc) 13.867 kb
60818b9 @ry Add missing copyright headers
ry authored
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
ff4a9d3 @bnoordhuis core: use proper #include directives
bnoordhuis authored
22 #include "node.h"
23 #include "node_buffer.h"
24 #include "handle_wrap.h"
1e13a2d @bnoordhuis stream_wrap: use new slab allocator
bnoordhuis authored
25 #include "slab_allocator.h"
ff4a9d3 @bnoordhuis core: use proper #include directives
bnoordhuis authored
26 #include "stream_wrap.h"
27 #include "pipe_wrap.h"
28 #include "tcp_wrap.h"
29 #include "req_wrap.h"
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
30
296b7a5 @bnoordhuis cluster: support passing of named pipes
bnoordhuis authored
31 #include <stdlib.h> // abort()
7d2e68f @bnoordhuis stream_wrap: fix compilation errors
bnoordhuis authored
32 #include <limits.h> // INT_MAX
296b7a5 @bnoordhuis cluster: support passing of named pipes
bnoordhuis authored
33
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
34 #define SLAB_SIZE (1024 * 1024)
35
36
1e13a2d @bnoordhuis stream_wrap: use new slab allocator
bnoordhuis authored
37 namespace node {
38
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
39 using v8::Object;
40 using v8::Handle;
41 using v8::Local;
42 using v8::Persistent;
43 using v8::Value;
44 using v8::HandleScope;
45 using v8::FunctionTemplate;
46 using v8::String;
47 using v8::Function;
48 using v8::TryCatch;
49 using v8::Context;
50 using v8::Arguments;
51 using v8::Integer;
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
52 using v8::Number;
53 using v8::Exception;
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
54
55
56 typedef class ReqWrap<uv_shutdown_t> ShutdownWrap;
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
57
58 class WriteWrap: public ReqWrap<uv_write_t> {
59 public:
60 void* operator new(size_t size, char* storage) { return storage; }
61
62 // This is just to keep the compiler happy. It should never be called, since
63 // we don't use exceptions in node.
64 void operator delete(void* ptr, char* storage) { assert(0); }
65
66 protected:
67 // People should not be using the non-placement new and delete operator on a
68 // WriteWrap. Ensure this never happens.
69 void* operator new (size_t size) { assert(0); };
70 void operator delete(void* ptr) { assert(0); };
71 };
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
72
73
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
74 static Persistent<String> buffer_sym;
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
75 static Persistent<String> bytes_sym;
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
76 static Persistent<String> write_queue_size_sym;
a26bee8 @isaacs MakeCallback: Consistent symbol usage
isaacs authored
77 static Persistent<String> onread_sym;
78 static Persistent<String> oncomplete_sym;
27061cc @bnoordhuis udp_wrap, stream_wrap: lazy init slab allocator
bnoordhuis authored
79 static SlabAllocator* slab_allocator;
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
80 static bool initialized;
81
82
27061cc @bnoordhuis udp_wrap, stream_wrap: lazy init slab allocator
bnoordhuis authored
83 static void DeleteSlabAllocator(void*) {
84 delete slab_allocator;
85 slab_allocator = NULL;
86 }
87
88
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
89 void StreamWrap::Initialize(Handle<Object> target) {
1e13a2d @bnoordhuis stream_wrap: use new slab allocator
bnoordhuis authored
90 if (initialized) return;
91 initialized = true;
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
92
27061cc @bnoordhuis udp_wrap, stream_wrap: lazy init slab allocator
bnoordhuis authored
93 slab_allocator = new SlabAllocator(SLAB_SIZE);
94 AtExit(DeleteSlabAllocator, NULL);
95
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
96 HandleScope scope;
97
0c7bf81 @ry Abstract out HandleWrap class
ry authored
98 HandleWrap::Initialize(target);
99
a26bee8 @isaacs MakeCallback: Consistent symbol usage
isaacs authored
100 buffer_sym = NODE_PSYMBOL("buffer");
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
101 bytes_sym = NODE_PSYMBOL("bytes");
a26bee8 @isaacs MakeCallback: Consistent symbol usage
isaacs authored
102 write_queue_size_sym = NODE_PSYMBOL("writeQueueSize");
103 onread_sym = NODE_PSYMBOL("onread");
104 oncomplete_sym = NODE_PSYMBOL("oncomplete");
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
105 }
106
107
0c7bf81 @ry Abstract out HandleWrap class
ry authored
108 StreamWrap::StreamWrap(Handle<Object> object, uv_stream_t* stream)
109 : HandleWrap(object, (uv_handle_t*)stream) {
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
110 stream_ = stream;
187fe27 stdio binding + javascript to enable process.stdin.listen()
Igor Zinkovsky authored
111 if (stream) {
112 stream->data = this;
113 }
114 }
115
116
117 void StreamWrap::SetHandle(uv_handle_t* h) {
118 HandleWrap::SetHandle(h);
119 stream_ = (uv_stream_t*)h;
120 stream_->data = this;
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
121 }
122
123
124 void StreamWrap::UpdateWriteQueueSize() {
6050af4 @ry net_uv: properly initialize writeQueueSize
ry authored
125 HandleScope scope;
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
126 object_->Set(write_queue_size_sym, Integer::New(stream_->write_queue_size));
127 }
128
129
130 Handle<Value> StreamWrap::ReadStart(const Arguments& args) {
131 HandleScope scope;
132
45de259 @Sannis Make UNWRAP macro generic.
Sannis authored
133 UNWRAP(StreamWrap)
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
134
471c570 @ry uv_write2 uv_read2_start binding
ry authored
135 bool ipc_pipe = wrap->stream_->type == UV_NAMED_PIPE &&
136 ((uv_pipe_t*)wrap->stream_)->ipc;
137 int r;
138 if (ipc_pipe) {
139 r = uv_read2_start(wrap->stream_, OnAlloc, OnRead2);
140 } else {
141 r = uv_read_start(wrap->stream_, OnAlloc, OnRead);
142 }
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
143
144 // Error starting the tcp.
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
145 if (r) SetErrno(uv_last_error(uv_default_loop()));
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
146
147 return scope.Close(Integer::New(r));
148 }
149
150
151 Handle<Value> StreamWrap::ReadStop(const Arguments& args) {
152 HandleScope scope;
153
45de259 @Sannis Make UNWRAP macro generic.
Sannis authored
154 UNWRAP(StreamWrap)
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
155
156 int r = uv_read_stop(wrap->stream_);
157
158 // Error starting the tcp.
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
159 if (r) SetErrno(uv_last_error(uv_default_loop()));
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
160
161 return scope.Close(Integer::New(r));
162 }
163
164
2aefea5 @bnoordhuis stream_wrap: update after libuv API change
bnoordhuis authored
165 uv_buf_t StreamWrap::OnAlloc(uv_handle_t* handle, size_t suggested_size) {
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
166 StreamWrap* wrap = static_cast<StreamWrap*>(handle->data);
2aefea5 @bnoordhuis stream_wrap: update after libuv API change
bnoordhuis authored
167 assert(wrap->stream_ == reinterpret_cast<uv_stream_t*>(handle));
27061cc @bnoordhuis udp_wrap, stream_wrap: lazy init slab allocator
bnoordhuis authored
168 char* buf = slab_allocator->Allocate(wrap->object_, suggested_size);
1e13a2d @bnoordhuis stream_wrap: use new slab allocator
bnoordhuis authored
169 return uv_buf_init(buf, suggested_size);
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
170 }
171
471c570 @ry uv_write2 uv_read2_start binding
ry authored
172
173 void StreamWrap::OnReadCommon(uv_stream_t* handle, ssize_t nread,
174 uv_buf_t buf, uv_handle_type pending) {
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
175 HandleScope scope;
176
177 StreamWrap* wrap = static_cast<StreamWrap*>(handle->data);
178
179 // We should not be getting this callback if someone as already called
180 // uv_close() on the handle.
181 assert(wrap->object_.IsEmpty() == false);
182
183 if (nread < 0) {
3ec84a1 @piscisaureus Slab allocator: don't attempt to shrink a non-buffer
piscisaureus authored
184 // If libuv reports an error or EOF it *may* give us a buffer back. In that
185 // case, return the space to the slab.
186 if (buf.base != NULL) {
27061cc @bnoordhuis udp_wrap, stream_wrap: lazy init slab allocator
bnoordhuis authored
187 slab_allocator->Shrink(wrap->object_, buf.base, 0);
3ec84a1 @piscisaureus Slab allocator: don't attempt to shrink a non-buffer
piscisaureus authored
188 }
189
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
190 SetErrno(uv_last_error(uv_default_loop()));
a26bee8 @isaacs MakeCallback: Consistent symbol usage
isaacs authored
191 MakeCallback(wrap->object_, onread_sym, 0, NULL);
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
192 return;
193 }
194
3ec84a1 @piscisaureus Slab allocator: don't attempt to shrink a non-buffer
piscisaureus authored
195 assert(buf.base != NULL);
27061cc @bnoordhuis udp_wrap, stream_wrap: lazy init slab allocator
bnoordhuis authored
196 Local<Object> slab = slab_allocator->Shrink(wrap->object_,
197 buf.base,
198 nread);
3ec84a1 @piscisaureus Slab allocator: don't attempt to shrink a non-buffer
piscisaureus authored
199
296b7a5 @bnoordhuis cluster: support passing of named pipes
bnoordhuis authored
200 if (nread == 0) return;
1e13a2d @bnoordhuis stream_wrap: use new slab allocator
bnoordhuis authored
201 assert(static_cast<size_t>(nread) <= buf.len);
471c570 @ry uv_write2 uv_read2_start binding
ry authored
202
296b7a5 @bnoordhuis cluster: support passing of named pipes
bnoordhuis authored
203 int argc = 3;
204 Local<Value> argv[4] = {
1e13a2d @bnoordhuis stream_wrap: use new slab allocator
bnoordhuis authored
205 slab,
206 Integer::NewFromUnsigned(buf.base - Buffer::Data(slab)),
207 Integer::NewFromUnsigned(nread)
296b7a5 @bnoordhuis cluster: support passing of named pipes
bnoordhuis authored
208 };
471c570 @ry uv_write2 uv_read2_start binding
ry authored
209
296b7a5 @bnoordhuis cluster: support passing of named pipes
bnoordhuis authored
210 Local<Object> pending_obj;
211 if (pending == UV_TCP) {
212 pending_obj = TCPWrap::Instantiate();
213 } else if (pending == UV_NAMED_PIPE) {
214 pending_obj = PipeWrap::Instantiate();
215 } else {
216 // We only support sending UV_TCP and UV_NAMED_PIPE right now.
217 assert(pending == UV_UNKNOWN_HANDLE);
218 }
471c570 @ry uv_write2 uv_read2_start binding
ry authored
219
296b7a5 @bnoordhuis cluster: support passing of named pipes
bnoordhuis authored
220 if (!pending_obj.IsEmpty()) {
221 assert(pending_obj->InternalFieldCount() > 0);
222 StreamWrap* pending_wrap =
223 static_cast<StreamWrap*>(pending_obj->GetPointerFromInternalField(0));
224 if (uv_accept(handle, pending_wrap->GetStream())) abort();
225 argv[3] = pending_obj;
226 argc++;
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
227 }
296b7a5 @bnoordhuis cluster: support passing of named pipes
bnoordhuis authored
228
a26bee8 @isaacs MakeCallback: Consistent symbol usage
isaacs authored
229 MakeCallback(wrap->object_, onread_sym, argc, argv);
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
230 }
231
232
471c570 @ry uv_write2 uv_read2_start binding
ry authored
233 void StreamWrap::OnRead(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
234 OnReadCommon(handle, nread, buf, UV_UNKNOWN_HANDLE);
235 }
236
237
238 void StreamWrap::OnRead2(uv_pipe_t* handle, ssize_t nread, uv_buf_t buf,
239 uv_handle_type pending) {
240 OnReadCommon((uv_stream_t*)handle, nread, buf, pending);
241 }
242
243
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
244 Handle<Value> StreamWrap::WriteBuffer(const Arguments& args) {
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
245 HandleScope scope;
246
45de259 @Sannis Make UNWRAP macro generic.
Sannis authored
247 UNWRAP(StreamWrap)
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
248
249 // The first argument is a buffer.
726ebad @piscisaureus StreamWrap::WriteBuffer: remove superfluous arguments
piscisaureus authored
250 assert(args.Length() >= 1 && Buffer::HasInstance(args[0]));
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
251 Local<Object> buffer_obj = args[0]->ToObject();
252 size_t offset = 0;
253 size_t length = Buffer::Length(buffer_obj);
254
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
255 if (length > INT_MAX) {
256 uv_err_t err;
257 err.code = UV_ENOBUFS;
258 SetErrno(err);
259 return scope.Close(v8::Null());
260 }
261
262 char* storage = new char[sizeof(WriteWrap)];
263 WriteWrap* req_wrap = new (storage) WriteWrap();
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
264
265 req_wrap->object_->SetHiddenValue(buffer_sym, buffer_obj);
266
267 uv_buf_t buf;
268 buf.base = Buffer::Data(buffer_obj) + offset;
269 buf.len = length;
270
726ebad @piscisaureus StreamWrap::WriteBuffer: remove superfluous arguments
piscisaureus authored
271 int r = uv_write(&req_wrap->req_,
272 wrap->stream_,
273 &buf,
274 1,
275 StreamWrap::AfterWrite);
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
276
277 req_wrap->Dispatched();
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
278 req_wrap->object_->Set(bytes_sym, Number::New((uint32_t) length));
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
279
280 wrap->UpdateWriteQueueSize();
281
282 if (r) {
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
283 SetErrno(uv_last_error(uv_default_loop()));
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
284 req_wrap->~WriteWrap();
285 delete[] storage;
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
286 return scope.Close(v8::Null());
287 } else {
288 return scope.Close(req_wrap->object_);
289 }
290 }
291
292
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
293 template <WriteEncoding encoding>
294 Handle<Value> StreamWrap::WriteStringImpl(const Arguments& args) {
295 HandleScope scope;
296 int r;
297
45de259 @Sannis Make UNWRAP macro generic.
Sannis authored
298 UNWRAP(StreamWrap)
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
299
300 if (args.Length() < 1)
301 return ThrowTypeError("Not enough arguments");
302
303 Local<String> string = args[0]->ToString();
304
305 // Compute the size of the storage that the string will be flattened into.
306 size_t storage_size;
307 switch (encoding) {
308 case kAscii:
309 storage_size = string->Length();
310 break;
311
312 case kUtf8:
313 if (!(string->MayContainNonAscii())) {
314 // If the string has only ascii characters, we know exactly how big
315 // the storage should be.
316 storage_size = string->Length();
317 } else if (string->Length() < 65536) {
318 // A single UCS2 codepoint never takes up more than 3 utf8 bytes.
319 // Unless the string is really long we just allocate so much space that
320 // we're certain the string fits in there entirely.
321 // TODO: maybe check handle->write_queue_size instead of string length?
322 storage_size = 3 * string->Length();
323 } else {
324 // The string is really long. Compute the allocation size that we
325 // actually need.
326 storage_size = string->Utf8Length();
327 }
328 break;
329
330 case kUcs2:
4624cf1 @piscisaureus stream_wrap.cc: fix typo
piscisaureus authored
331 storage_size = string->Length() * sizeof(uint16_t);
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
332 break;
333
334 default:
335 // Unreachable.
336 assert(0);
337 }
338
339 if (storage_size > INT_MAX) {
340 uv_err_t err;
341 err.code = UV_ENOBUFS;
342 SetErrno(err);
343 return scope.Close(v8::Null());
344 }
345
346 char* storage = new char[sizeof(WriteWrap) + storage_size + 15];
347 WriteWrap* req_wrap = new (storage) WriteWrap();
348
349 char* data = reinterpret_cast<char*>(ROUND_UP(
350 reinterpret_cast<uintptr_t>(storage) + sizeof(WriteWrap), 16));
351 size_t data_size;
352 switch (encoding) {
353 case kAscii:
354 data_size = string->WriteAscii(data, 0, -1,
355 String::NO_NULL_TERMINATION | String::HINT_MANY_WRITES_EXPECTED);
356 break;
357
358 case kUtf8:
359 data_size = string->WriteUtf8(data, -1, NULL,
360 String::NO_NULL_TERMINATION | String::HINT_MANY_WRITES_EXPECTED);
361 break;
362
363 case kUcs2: {
364 int chars_copied = string->Write((uint16_t*) data, 0, -1,
365 String::NO_NULL_TERMINATION | String::HINT_MANY_WRITES_EXPECTED);
366 data_size = chars_copied * sizeof(uint16_t);
367 break;
368 }
369
370 default:
371 // Unreachable
372 assert(0);
373 }
374
375 assert(data_size <= storage_size);
376
377 uv_buf_t buf;
378 buf.base = data;
379 buf.len = data_size;
380
381 bool ipc_pipe = wrap->stream_->type == UV_NAMED_PIPE &&
382 ((uv_pipe_t*)wrap->stream_)->ipc;
383
384 if (!ipc_pipe) {
385 r = uv_write(&req_wrap->req_,
386 wrap->stream_,
387 &buf,
388 1,
389 StreamWrap::AfterWrite);
390
391 } else {
392 uv_stream_t* send_stream = NULL;
393
394 if (args[1]->IsObject()) {
395 Local<Object> send_stream_obj = args[1]->ToObject();
396 assert(send_stream_obj->InternalFieldCount() > 0);
397 StreamWrap* send_stream_wrap = static_cast<StreamWrap*>(
398 send_stream_obj->GetPointerFromInternalField(0));
399 send_stream = send_stream_wrap->GetStream();
400 }
401
402 r = uv_write2(&req_wrap->req_,
403 wrap->stream_,
404 &buf,
405 1,
406 send_stream,
407 StreamWrap::AfterWrite);
408 }
409
410 req_wrap->Dispatched();
411 req_wrap->object_->Set(bytes_sym, Number::New((uint32_t) data_size));
412
413 wrap->UpdateWriteQueueSize();
414
415 if (r) {
416 SetErrno(uv_last_error(uv_default_loop()));
417 req_wrap->~WriteWrap();
418 delete[] storage;
419 return scope.Close(v8::Null());
420 } else {
421 return scope.Close(req_wrap->object_);
422 }
423 }
424
425
426 Handle<Value> StreamWrap::WriteAsciiString(const Arguments& args) {
427 return WriteStringImpl<kAscii>(args);
428 }
429
430
431 Handle<Value> StreamWrap::WriteUtf8String(const Arguments& args) {
432 return WriteStringImpl<kUtf8>(args);
433 }
434
435
436 Handle<Value> StreamWrap::WriteUcs2String(const Arguments& args) {
437 return WriteStringImpl<kUcs2>(args);
438 }
439
440
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
441 void StreamWrap::AfterWrite(uv_write_t* req, int status) {
442 WriteWrap* req_wrap = (WriteWrap*) req->data;
443 StreamWrap* wrap = (StreamWrap*) req->handle->data;
444
445 HandleScope scope;
446
447 // The wrap and request objects should still be there.
448 assert(req_wrap->object_.IsEmpty() == false);
449 assert(wrap->object_.IsEmpty() == false);
450
451 if (status) {
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
452 SetErrno(uv_last_error(uv_default_loop()));
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
453 }
454
455 wrap->UpdateWriteQueueSize();
456
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
457 Local<Value> argv[] = {
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
458 Integer::New(status),
459 Local<Value>::New(wrap->object_),
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
460 Local<Value>::New(req_wrap->object_)
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
461 };
462
a26bee8 @isaacs MakeCallback: Consistent symbol usage
isaacs authored
463 MakeCallback(req_wrap->object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
464
0e57aaf @piscisaureus Optimize writing strings with Socket.write
piscisaureus authored
465 req_wrap->~WriteWrap();
466 delete[] reinterpret_cast<char*>(req_wrap);
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
467 }
468
469
470 Handle<Value> StreamWrap::Shutdown(const Arguments& args) {
471 HandleScope scope;
472
45de259 @Sannis Make UNWRAP macro generic.
Sannis authored
473 UNWRAP(StreamWrap)
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
474
475 ShutdownWrap* req_wrap = new ShutdownWrap();
476
477 int r = uv_shutdown(&req_wrap->req_, wrap->stream_, AfterShutdown);
478
479 req_wrap->Dispatched();
480
481 if (r) {
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
482 SetErrno(uv_last_error(uv_default_loop()));
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
483 delete req_wrap;
484 return scope.Close(v8::Null());
485 } else {
486 return scope.Close(req_wrap->object_);
487 }
488 }
489
490
491 void StreamWrap::AfterShutdown(uv_shutdown_t* req, int status) {
492 ReqWrap<uv_shutdown_t>* req_wrap = (ReqWrap<uv_shutdown_t>*) req->data;
493 StreamWrap* wrap = (StreamWrap*) req->handle->data;
494
495 // The wrap and request objects should still be there.
496 assert(req_wrap->object_.IsEmpty() == false);
497 assert(wrap->object_.IsEmpty() == false);
498
499 HandleScope scope;
500
501 if (status) {
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
502 SetErrno(uv_last_error(uv_default_loop()));
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
503 }
504
505 Local<Value> argv[3] = {
506 Integer::New(status),
507 Local<Value>::New(wrap->object_),
508 Local<Value>::New(req_wrap->object_)
509 };
510
a26bee8 @isaacs MakeCallback: Consistent symbol usage
isaacs authored
511 MakeCallback(req_wrap->object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
1ae1489 @ry Abstract StreamWrap from TCPWrap
ry authored
512
513 delete req_wrap;
514 }
515
516
517 }
Something went wrong with that request. Please try again.