GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: pipe_wrap.cc Lines: 109 112 97.3 %
Date: 2022-08-16 04:20:39 Branches: 24 42 57.1 %

Line Branch Exec Source
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 "pipe_wrap.h"
23
24
#include "async_wrap.h"
25
#include "connect_wrap.h"
26
#include "connection_wrap.h"
27
#include "env-inl.h"
28
#include "handle_wrap.h"
29
#include "node.h"
30
#include "node_buffer.h"
31
#include "node_external_reference.h"
32
#include "stream_base-inl.h"
33
#include "stream_wrap.h"
34
#include "util-inl.h"
35
36
namespace node {
37
38
using v8::Context;
39
using v8::EscapableHandleScope;
40
using v8::Function;
41
using v8::FunctionCallbackInfo;
42
using v8::FunctionTemplate;
43
using v8::Int32;
44
using v8::Isolate;
45
using v8::Local;
46
using v8::MaybeLocal;
47
using v8::Object;
48
using v8::Value;
49
50
76
MaybeLocal<Object> PipeWrap::Instantiate(Environment* env,
51
                                         AsyncWrap* parent,
52
                                         PipeWrap::SocketType type) {
53
76
  EscapableHandleScope handle_scope(env->isolate());
54
76
  AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(parent);
55
152
  CHECK_EQ(false, env->pipe_constructor_template().IsEmpty());
56
76
  Local<Function> constructor = env->pipe_constructor_template()
57
76
                                    ->GetFunction(env->context())
58
76
                                    .ToLocalChecked();
59
76
  CHECK_EQ(false, constructor.IsEmpty());
60
152
  Local<Value> type_value = Int32::New(env->isolate(), type);
61
  return handle_scope.EscapeMaybe(
62
152
      constructor->NewInstance(env->context(), 1, &type_value));
63
}
64
65
66
6065
void PipeWrap::Initialize(Local<Object> target,
67
                          Local<Value> unused,
68
                          Local<Context> context,
69
                          void* priv) {
70
6065
  Environment* env = Environment::GetCurrent(context);
71
6065
  Isolate* isolate = env->isolate();
72
73
6065
  Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
74
12130
  t->InstanceTemplate()
75
6065
    ->SetInternalFieldCount(StreamBase::kInternalFieldCount);
76
77
6065
  t->Inherit(LibuvStreamWrap::GetConstructorTemplate(env));
78
79
6065
  SetProtoMethod(isolate, t, "bind", Bind);
80
6065
  SetProtoMethod(isolate, t, "listen", Listen);
81
6065
  SetProtoMethod(isolate, t, "connect", Connect);
82
6065
  SetProtoMethod(isolate, t, "open", Open);
83
84
#ifdef _WIN32
85
  SetProtoMethod(isolate, t, "setPendingInstances", SetPendingInstances);
86
#endif
87
88
6065
  SetProtoMethod(isolate, t, "fchmod", Fchmod);
89
90
6065
  SetConstructorFunction(context, target, "Pipe", t);
91
6065
  env->set_pipe_constructor_template(t);
92
93
  // Create FunctionTemplate for PipeConnectWrap.
94
6065
  auto cwt = BaseObject::MakeLazilyInitializedJSTemplate(env);
95
6065
  cwt->Inherit(AsyncWrap::GetConstructorTemplate(env));
96
6065
  SetConstructorFunction(context, target, "PipeConnectWrap", cwt);
97
98
  // Define constants
99
6065
  Local<Object> constants = Object::New(env->isolate());
100
18195
  NODE_DEFINE_CONSTANT(constants, SOCKET);
101
18195
  NODE_DEFINE_CONSTANT(constants, SERVER);
102
18195
  NODE_DEFINE_CONSTANT(constants, IPC);
103
18195
  NODE_DEFINE_CONSTANT(constants, UV_READABLE);
104
18195
  NODE_DEFINE_CONSTANT(constants, UV_WRITABLE);
105
6065
  target->Set(context,
106
              env->constants_string(),
107
12130
              constants).Check();
108
6065
}
109
110
5338
void PipeWrap::RegisterExternalReferences(ExternalReferenceRegistry* registry) {
111
5338
  registry->Register(New);
112
5338
  registry->Register(Bind);
113
5338
  registry->Register(Listen);
114
5338
  registry->Register(Connect);
115
5338
  registry->Register(Open);
116
#ifdef _WIN32
117
  registry->Register(SetPendingInstances);
118
#endif
119
5338
  registry->Register(Fchmod);
120
5338
}
121
122
6202
void PipeWrap::New(const FunctionCallbackInfo<Value>& args) {
123
  // This constructor should not be exposed to public javascript.
124
  // Therefore we assert that we are not trying to call this as a
125
  // normal function.
126
6202
  CHECK(args.IsConstructCall());
127
6202
  CHECK(args[0]->IsInt32());
128
6202
  Environment* env = Environment::GetCurrent(args);
129
130
12404
  int type_value = args[0].As<Int32>()->Value();
131
6202
  PipeWrap::SocketType type = static_cast<PipeWrap::SocketType>(type_value);
132
133
  bool ipc;
134
  ProviderType provider;
135

6202
  switch (type) {
136
5245
    case SOCKET:
137
5245
      provider = PROVIDER_PIPEWRAP;
138
5245
      ipc = false;
139
5245
      break;
140
53
    case SERVER:
141
53
      provider = PROVIDER_PIPESERVERWRAP;
142
53
      ipc = false;
143
53
      break;
144
904
    case IPC:
145
904
      provider = PROVIDER_PIPEWRAP;
146
904
      ipc = true;
147
904
      break;
148
    default:
149
      UNREACHABLE();
150
  }
151
152
6202
  new PipeWrap(env, args.This(), provider, ipc);
153
6202
}
154
155
156
6202
PipeWrap::PipeWrap(Environment* env,
157
                   Local<Object> object,
158
                   ProviderType provider,
159
6202
                   bool ipc)
160
6202
    : ConnectionWrap(env, object, provider) {
161
6202
  int r = uv_pipe_init(env->event_loop(), &handle_, ipc);
162
6202
  CHECK_EQ(r, 0);  // How do we proxy this error up to javascript?
163
                   // Suggestion: uv_pipe_init() returns void.
164
6202
}
165
166
167
58
void PipeWrap::Bind(const FunctionCallbackInfo<Value>& args) {
168
  PipeWrap* wrap;
169
58
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
170
58
  node::Utf8Value name(args.GetIsolate(), args[0]);
171
58
  int err = uv_pipe_bind(&wrap->handle_, *name);
172
116
  args.GetReturnValue().Set(err);
173
}
174
175
176
#ifdef _WIN32
177
void PipeWrap::SetPendingInstances(const FunctionCallbackInfo<Value>& args) {
178
  PipeWrap* wrap;
179
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
180
  CHECK(args[0]->IsInt32());
181
  int instances = args[0].As<Int32>()->Value();
182
  uv_pipe_pending_instances(&wrap->handle_, instances);
183
}
184
#endif
185
186
187
2
void PipeWrap::Fchmod(const v8::FunctionCallbackInfo<v8::Value>& args) {
188
  PipeWrap* wrap;
189
2
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
190
2
  CHECK(args[0]->IsInt32());
191
4
  int mode = args[0].As<Int32>()->Value();
192
2
  int err = uv_pipe_chmod(&wrap->handle_, mode);
193
4
  args.GetReturnValue().Set(err);
194
}
195
196
197
50
void PipeWrap::Listen(const FunctionCallbackInfo<Value>& args) {
198
  PipeWrap* wrap;
199
50
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
200
50
  Environment* env = wrap->env();
201
  int backlog;
202
100
  if (!args[0]->Int32Value(env->context()).To(&backlog)) return;
203
50
  int err = uv_listen(reinterpret_cast<uv_stream_t*>(&wrap->handle_),
204
                      backlog,
205
                      OnConnection);
206
100
  args.GetReturnValue().Set(err);
207
}
208
209
210
1764
void PipeWrap::Open(const FunctionCallbackInfo<Value>& args) {
211
1764
  Environment* env = Environment::GetCurrent(args);
212
213
  PipeWrap* wrap;
214
1764
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
215
216
  int fd;
217
3528
  if (!args[0]->Int32Value(env->context()).To(&fd)) return;
218
219
1764
  int err = uv_pipe_open(&wrap->handle_, fd);
220
1764
  wrap->set_fd(fd);
221
222
1764
  if (err != 0)
223
    env->ThrowUVException(err, "uv_pipe_open");
224
}
225
226
227
59
void PipeWrap::Connect(const FunctionCallbackInfo<Value>& args) {
228
59
  Environment* env = Environment::GetCurrent(args);
229
230
  PipeWrap* wrap;
231
59
  ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
232
233
59
  CHECK(args[0]->IsObject());
234
118
  CHECK(args[1]->IsString());
235
236
118
  Local<Object> req_wrap_obj = args[0].As<Object>();
237
59
  node::Utf8Value name(env->isolate(), args[1]);
238
239
  ConnectWrap* req_wrap =
240
59
      new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_PIPECONNECTWRAP);
241
59
  req_wrap->Dispatch(uv_pipe_connect,
242
59
                     &wrap->handle_,
243
                     *name,
244
                     AfterConnect);
245
246

88
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(TRACING_CATEGORY_NODE2(net, native),
247
                                    "connect",
248
                                    req_wrap,
249
                                    "pipe_path",
250
                                    TRACE_STR_COPY(*name));
251
252
118
  args.GetReturnValue().Set(0);  // uv_pipe_connect() doesn't return errors.
253
}
254
255
256
}  // namespace node
257
258
5410
NODE_MODULE_CONTEXT_AWARE_INTERNAL(pipe_wrap, node::PipeWrap::Initialize)
259
5338
NODE_MODULE_EXTERNAL_REFERENCE(pipe_wrap,
260
                               node::PipeWrap::RegisterExternalReferences)