~james-page/ubuntu/precise/nodejs/0.6.x-merge

« back to all changes in this revision

Viewing changes to src/pipe_wrap.cc

  • Committer: James Page
  • Date: 2012-03-30 12:09:16 UTC
  • mfrom: (7.1.23 sid)
  • Revision ID: james.page@canonical.com-20120330120916-40hfu9o00qr5t87b
* Merge from Debian unstable:
  - New upstream release (LP: #892034).
  - This package is x86/arm only. Update control to match
  - d/patches/2009_increase_test_timeout.patch: Increased default test
    timeout from 60 to 120 seconds to support reliable execution of all
    tests on armhf/armel architectures.
  - d/patches/2005_expected_failing_tests.patch: 
    - Allow racey tests to fail: test-cluster-kill-workers,
      test-child-process-fork2 
    - Allow test-fs-watch to fail as LP buildd's don't support
      inotify.
    - Revert all other Ubuntu changes as no longer required.
* Update Standards-Version to 3.9.3.
* Patch wscript to enable build on mipsel arch, libv8 being available.
  Upstream does not support that arch, failure expected.
* test-cluster-kill-workers is expected to fail on armhf,
  Bug#660802 will be closed when test pass.
* test-buffer is expected to fail on armel,
  Bug#660800 will be closed when test pass.
* Add epoch to dependency on libev >= 1:4.11. Closes: bug#658441.
* Remove tools/doc because node-doc-generator has no license for now.
* Add copyright for doc/sh* files (shjs).
* source.lintian-overrides : source-contains-waf-binary tools/node-waf
  it is simply not the case here.
* test-stream-pipe-multi expected to timeout sometimes on busy builds. 
* New upstream release.
* Remove upstream patches.
* test-dgram-pingpong expected to timeout, the test itself is buggy.
* test-buffer expected to fail on armel, allow building package to make
  it easier to find the cause of the failure.
  Closes: bug#639636.
* Expect tests dgram-multicast and broadcast to fail.
  debian/patches/2005_expected_failing_tests.patch
* Drop dpkg-source local-options: Defaults since dpkg-source 1.16.1.
* New upstream release.
* Depend on libev-dev 4.11, see bug#657080.
* Bump dependency on openssl to 1.0.0g.
* Remove useless uv_loop_refcount from libuv,
  refreshed 2009_fix_shared_ev.patch.
* Apply to upstream patches landed after 0.6.10 release,
  to fix debugger repl and http client.
* New upstream release. Closes:bug#650661
* Repackage to remove non-dfsg font files ./deps/npm/html/*/*.ttf
* Remove unneeded bundled dependencies: lighter tarball,
  debian/copyright is easier to maintain.
* Drop unneeded build-dependency on scons.
* Depend on zlib1g, libc-ares, libev.
  Patches done to support building with those shared libs.
* Fix DEB_UPSTREAM_URL in debian/rules, and debian/watch.
* nodejs.pc file for pkgconfig is no more available.
* Build-depend on procps package, a test is using /bin/ps.
* Refreshed debian/patches/2005_expected_failing_tests.patch,
  only for tests that need networking.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <req_wrap.h>
 
25
#include <handle_wrap.h>
 
26
#include <stream_wrap.h>
 
27
#include <pipe_wrap.h>
 
28
 
 
29
#define UNWRAP \
 
30
  assert(!args.Holder().IsEmpty()); \
 
31
  assert(args.Holder()->InternalFieldCount() > 0); \
 
32
  PipeWrap* wrap =  \
 
33
      static_cast<PipeWrap*>(args.Holder()->GetPointerFromInternalField(0)); \
 
34
  if (!wrap) { \
 
35
    uv_err_t err; \
 
36
    err.code = UV_EBADF; \
 
37
    SetErrno(err); \
 
38
    return scope.Close(Integer::New(-1)); \
 
39
  }
 
40
 
 
41
namespace node {
 
42
 
 
43
using v8::Object;
 
44
using v8::Handle;
 
45
using v8::Local;
 
46
using v8::Persistent;
 
47
using v8::Value;
 
48
using v8::HandleScope;
 
49
using v8::FunctionTemplate;
 
50
using v8::String;
 
51
using v8::Function;
 
52
using v8::TryCatch;
 
53
using v8::Context;
 
54
using v8::Arguments;
 
55
using v8::Integer;
 
56
using v8::Boolean;
 
57
 
 
58
Persistent<Function> pipeConstructor;
 
59
 
 
60
 
 
61
// TODO share with TCPWrap?
 
62
typedef class ReqWrap<uv_connect_t> ConnectWrap;
 
63
 
 
64
 
 
65
uv_pipe_t* PipeWrap::UVHandle() {
 
66
  return &handle_;
 
67
}
 
68
 
 
69
 
 
70
PipeWrap* PipeWrap::Unwrap(Local<Object> obj) {
 
71
  assert(!obj.IsEmpty());
 
72
  assert(obj->InternalFieldCount() > 0);
 
73
  return static_cast<PipeWrap*>(obj->GetPointerFromInternalField(0));
 
74
}
 
75
 
 
76
 
 
77
void PipeWrap::Initialize(Handle<Object> target) {
 
78
  StreamWrap::Initialize(target);
 
79
 
 
80
  HandleScope scope;
 
81
 
 
82
  Local<FunctionTemplate> t = FunctionTemplate::New(New);
 
83
  t->SetClassName(String::NewSymbol("Pipe"));
 
84
 
 
85
  t->InstanceTemplate()->SetInternalFieldCount(1);
 
86
 
 
87
  NODE_SET_PROTOTYPE_METHOD(t, "close", HandleWrap::Close);
 
88
  NODE_SET_PROTOTYPE_METHOD(t, "unref", HandleWrap::Unref);
 
89
  NODE_SET_PROTOTYPE_METHOD(t, "ref", HandleWrap::Ref);
 
90
 
 
91
  NODE_SET_PROTOTYPE_METHOD(t, "readStart", StreamWrap::ReadStart);
 
92
  NODE_SET_PROTOTYPE_METHOD(t, "readStop", StreamWrap::ReadStop);
 
93
  NODE_SET_PROTOTYPE_METHOD(t, "write", StreamWrap::Write);
 
94
  NODE_SET_PROTOTYPE_METHOD(t, "shutdown", StreamWrap::Shutdown);
 
95
 
 
96
  NODE_SET_PROTOTYPE_METHOD(t, "bind", Bind);
 
97
  NODE_SET_PROTOTYPE_METHOD(t, "listen", Listen);
 
98
  NODE_SET_PROTOTYPE_METHOD(t, "connect", Connect);
 
99
  NODE_SET_PROTOTYPE_METHOD(t, "open", Open);
 
100
 
 
101
#ifdef _WIN32
 
102
  NODE_SET_PROTOTYPE_METHOD(t, "setPendingInstances", SetPendingInstances);
 
103
#endif
 
104
 
 
105
  pipeConstructor = Persistent<Function>::New(t->GetFunction());
 
106
 
 
107
  target->Set(String::NewSymbol("Pipe"), pipeConstructor);
 
108
}
 
109
 
 
110
 
 
111
Handle<Value> PipeWrap::New(const Arguments& args) {
 
112
  // This constructor should not be exposed to public javascript.
 
113
  // Therefore we assert that we are not trying to call this as a
 
114
  // normal function.
 
115
  assert(args.IsConstructCall());
 
116
 
 
117
  HandleScope scope;
 
118
  PipeWrap* wrap = new PipeWrap(args.This(), args[0]->IsTrue());
 
119
  assert(wrap);
 
120
 
 
121
  return scope.Close(args.This());
 
122
}
 
123
 
 
124
 
 
125
PipeWrap::PipeWrap(Handle<Object> object, bool ipc)
 
126
    : StreamWrap(object, (uv_stream_t*) &handle_) {
 
127
  int r = uv_pipe_init(uv_default_loop(), &handle_, ipc);
 
128
  assert(r == 0); // How do we proxy this error up to javascript?
 
129
                  // Suggestion: uv_pipe_init() returns void.
 
130
  handle_.data = reinterpret_cast<void*>(this);
 
131
  UpdateWriteQueueSize();
 
132
}
 
133
 
 
134
 
 
135
Handle<Value> PipeWrap::Bind(const Arguments& args) {
 
136
  HandleScope scope;
 
137
 
 
138
  UNWRAP
 
139
 
 
140
  String::AsciiValue name(args[0]->ToString());
 
141
 
 
142
  int r = uv_pipe_bind(&wrap->handle_, *name);
 
143
 
 
144
  // Error starting the pipe.
 
145
  if (r) SetErrno(uv_last_error(uv_default_loop()));
 
146
 
 
147
  return scope.Close(Integer::New(r));
 
148
}
 
149
 
 
150
 
 
151
#ifdef _WIN32
 
152
Handle<Value> PipeWrap::SetPendingInstances(const Arguments& args) {
 
153
  HandleScope scope;
 
154
 
 
155
  UNWRAP
 
156
 
 
157
  int instances = args[0]->Int32Value();
 
158
 
 
159
  uv_pipe_pending_instances(&wrap->handle_, instances);
 
160
 
 
161
  return v8::Null();
 
162
}
 
163
#endif
 
164
 
 
165
 
 
166
Handle<Value> PipeWrap::Listen(const Arguments& args) {
 
167
  HandleScope scope;
 
168
 
 
169
  UNWRAP
 
170
 
 
171
  int backlog = args[0]->Int32Value();
 
172
 
 
173
  int r = uv_listen((uv_stream_t*)&wrap->handle_, backlog, OnConnection);
 
174
 
 
175
  // Error starting the pipe.
 
176
  if (r) SetErrno(uv_last_error(uv_default_loop()));
 
177
 
 
178
  return scope.Close(Integer::New(r));
 
179
}
 
180
 
 
181
 
 
182
// TODO maybe share with TCPWrap?
 
183
void PipeWrap::OnConnection(uv_stream_t* handle, int status) {
 
184
  HandleScope scope;
 
185
 
 
186
  PipeWrap* wrap = static_cast<PipeWrap*>(handle->data);
 
187
  assert(&wrap->handle_ == (uv_pipe_t*)handle);
 
188
 
 
189
  // We should not be getting this callback if someone as already called
 
190
  // uv_close() on the handle.
 
191
  assert(wrap->object_.IsEmpty() == false);
 
192
 
 
193
  if (status != 0) {
 
194
    // TODO Handle server error (set errno and call onconnection with NULL)
 
195
    assert(0);
 
196
    return;
 
197
  }
 
198
 
 
199
  // Instanciate the client javascript object and handle.
 
200
  Local<Object> client_obj = pipeConstructor->NewInstance();
 
201
 
 
202
  // Unwrap the client javascript object.
 
203
  assert(client_obj->InternalFieldCount() > 0);
 
204
  PipeWrap* client_wrap =
 
205
      static_cast<PipeWrap*>(client_obj->GetPointerFromInternalField(0));
 
206
 
 
207
  if (uv_accept(handle, (uv_stream_t*)&client_wrap->handle_)) return;
 
208
 
 
209
  // Successful accept. Call the onconnection callback in JavaScript land.
 
210
  Local<Value> argv[1] = { client_obj };
 
211
  MakeCallback(wrap->object_, "onconnection", 1, argv);
 
212
}
 
213
 
 
214
// TODO Maybe share this with TCPWrap?
 
215
void PipeWrap::AfterConnect(uv_connect_t* req, int status) {
 
216
  ConnectWrap* req_wrap = (ConnectWrap*) req->data;
 
217
  PipeWrap* wrap = (PipeWrap*) req->handle->data;
 
218
 
 
219
  HandleScope scope;
 
220
 
 
221
  // The wrap and request objects should still be there.
 
222
  assert(req_wrap->object_.IsEmpty() == false);
 
223
  assert(wrap->object_.IsEmpty() == false);
 
224
 
 
225
  bool readable, writable;
 
226
 
 
227
  if (status) {
 
228
    SetErrno(uv_last_error(uv_default_loop()));
 
229
    readable = writable = 0;
 
230
  } else {
 
231
    readable = uv_is_readable(req->handle) != 0;
 
232
    writable = uv_is_writable(req->handle) != 0;
 
233
  }
 
234
 
 
235
  Local<Value> argv[5] = {
 
236
    Integer::New(status),
 
237
    Local<Value>::New(wrap->object_),
 
238
    Local<Value>::New(req_wrap->object_),
 
239
    Local<Value>::New(Boolean::New(readable)),
 
240
    Local<Value>::New(Boolean::New(writable))
 
241
  };
 
242
 
 
243
  MakeCallback(req_wrap->object_, "oncomplete", 5, argv);
 
244
 
 
245
  delete req_wrap;
 
246
}
 
247
 
 
248
 
 
249
Handle<Value> PipeWrap::Open(const Arguments& args) {
 
250
  HandleScope scope;
 
251
 
 
252
  UNWRAP
 
253
 
 
254
  int fd = args[0]->IntegerValue();
 
255
 
 
256
  uv_pipe_open(&wrap->handle_, fd);
 
257
 
 
258
  return scope.Close(v8::Null());
 
259
}
 
260
 
 
261
 
 
262
Handle<Value> PipeWrap::Connect(const Arguments& args) {
 
263
  HandleScope scope;
 
264
 
 
265
  UNWRAP
 
266
 
 
267
  String::AsciiValue name(args[0]->ToString());
 
268
 
 
269
  ConnectWrap* req_wrap = new ConnectWrap();
 
270
 
 
271
  uv_pipe_connect(&req_wrap->req_,
 
272
                  &wrap->handle_,
 
273
                  *name,
 
274
                  AfterConnect);
 
275
 
 
276
  req_wrap->Dispatched();
 
277
 
 
278
  return scope.Close(req_wrap->object_);
 
279
}
 
280
 
 
281
 
 
282
}  // namespace node
 
283
 
 
284
NODE_MODULE(node_pipe_wrap, node::PipeWrap::Initialize)