1 |
|
|
#include "connection_wrap.h" |
2 |
|
|
|
3 |
|
|
#include "connect_wrap.h" |
4 |
|
|
#include "env-inl.h" |
5 |
|
|
#include "pipe_wrap.h" |
6 |
|
|
#include "stream_base-inl.h" |
7 |
|
|
#include "stream_wrap.h" |
8 |
|
|
#include "tcp_wrap.h" |
9 |
|
|
#include "util-inl.h" |
10 |
|
|
|
11 |
|
|
namespace node { |
12 |
|
|
|
13 |
|
|
using v8::Boolean; |
14 |
|
|
using v8::Context; |
15 |
|
|
using v8::HandleScope; |
16 |
|
|
using v8::Integer; |
17 |
|
|
using v8::Local; |
18 |
|
|
using v8::Object; |
19 |
|
|
using v8::Value; |
20 |
|
|
|
21 |
|
|
|
22 |
|
|
template <typename WrapType, typename UVType> |
23 |
|
40004 |
ConnectionWrap<WrapType, UVType>::ConnectionWrap(Environment* env, |
24 |
|
|
Local<Object> object, |
25 |
|
|
ProviderType provider) |
26 |
|
|
: LibuvStreamWrap(env, |
27 |
|
|
object, |
28 |
|
40004 |
reinterpret_cast<uv_stream_t*>(&handle_), |
29 |
|
40004 |
provider) {} |
30 |
|
|
|
31 |
|
|
|
32 |
|
|
template <typename WrapType, typename UVType> |
33 |
|
9972 |
void ConnectionWrap<WrapType, UVType>::OnConnection(uv_stream_t* handle, |
34 |
|
|
int status) { |
35 |
|
9972 |
WrapType* wrap_data = static_cast<WrapType*>(handle->data); |
36 |
✗✓ |
9972 |
CHECK_NOT_NULL(wrap_data); |
37 |
✗✓ |
9972 |
CHECK_EQ(&wrap_data->handle_, reinterpret_cast<UVType*>(handle)); |
38 |
|
|
|
39 |
|
9972 |
Environment* env = wrap_data->env(); |
40 |
|
9972 |
HandleScope handle_scope(env->isolate()); |
41 |
|
9972 |
Context::Scope context_scope(env->context()); |
42 |
|
|
|
43 |
|
|
// We should not be getting this callback if someone has already called |
44 |
|
|
// uv_close() on the handle. |
45 |
✗✓ |
9972 |
CHECK_EQ(wrap_data->persistent().IsEmpty(), false); |
46 |
|
|
|
47 |
|
|
Local<Value> client_handle; |
48 |
|
|
|
49 |
✓✗ |
9972 |
if (status == 0) { |
50 |
|
|
// Instantiate the client javascript object and handle. |
51 |
|
|
Local<Object> client_obj; |
52 |
✗✓ |
19944 |
if (!WrapType::Instantiate(env, wrap_data, WrapType::SOCKET) |
53 |
|
|
.ToLocal(&client_obj)) |
54 |
|
|
return; |
55 |
|
|
|
56 |
|
|
// Unwrap the client javascript object. |
57 |
|
|
WrapType* wrap; |
58 |
✗✓ |
9972 |
ASSIGN_OR_RETURN_UNWRAP(&wrap, client_obj); |
59 |
|
9972 |
uv_stream_t* client = reinterpret_cast<uv_stream_t*>(&wrap->handle_); |
60 |
|
|
// uv_accept can fail if the new connection has already been closed, in |
61 |
|
|
// which case an EAGAIN (resource temporarily unavailable) will be |
62 |
|
|
// returned. |
63 |
✗✓ |
9972 |
if (uv_accept(handle, client)) |
64 |
|
|
return; |
65 |
|
|
|
66 |
|
|
// Successful accept. Call the onconnection callback in JavaScript land. |
67 |
|
9972 |
client_handle = client_obj; |
68 |
|
|
} else { |
69 |
|
|
client_handle = Undefined(env->isolate()); |
70 |
|
|
} |
71 |
|
|
|
72 |
|
9972 |
Local<Value> argv[] = { Integer::New(env->isolate(), status), client_handle }; |
73 |
|
9972 |
wrap_data->MakeCallback(env->onconnection_string(), arraysize(argv), argv); |
74 |
|
|
} |
75 |
|
|
|
76 |
|
|
|
77 |
|
|
template <typename WrapType, typename UVType> |
78 |
|
11150 |
void ConnectionWrap<WrapType, UVType>::AfterConnect(uv_connect_t* req, |
79 |
|
|
int status) { |
80 |
|
22300 |
BaseObjectPtr<ConnectWrap> req_wrap{static_cast<ConnectWrap*>(req->data)}; |
81 |
✗✓ |
11150 |
CHECK(req_wrap); |
82 |
|
11150 |
WrapType* wrap = static_cast<WrapType*>(req->handle->data); |
83 |
✗✓ |
11150 |
CHECK_EQ(req_wrap->env(), wrap->env()); |
84 |
|
11150 |
Environment* env = wrap->env(); |
85 |
|
|
|
86 |
|
22300 |
HandleScope handle_scope(env->isolate()); |
87 |
|
11150 |
Context::Scope context_scope(env->context()); |
88 |
|
|
|
89 |
|
|
// The wrap and request objects should still be there. |
90 |
✗✓ |
11150 |
CHECK_EQ(req_wrap->persistent().IsEmpty(), false); |
91 |
✗✓ |
11150 |
CHECK_EQ(wrap->persistent().IsEmpty(), false); |
92 |
|
|
|
93 |
|
|
bool readable, writable; |
94 |
|
|
|
95 |
✓✓ |
11150 |
if (status) { |
96 |
|
834 |
readable = writable = false; |
97 |
|
|
} else { |
98 |
|
10316 |
readable = uv_is_readable(req->handle) != 0; |
99 |
|
10316 |
writable = uv_is_writable(req->handle) != 0; |
100 |
|
|
} |
101 |
|
|
|
102 |
|
66900 |
Local<Value> argv[5] = { |
103 |
|
|
Integer::New(env->isolate(), status), |
104 |
|
|
wrap->object(), |
105 |
|
11150 |
req_wrap->object(), |
106 |
|
|
Boolean::New(env->isolate(), readable), |
107 |
|
|
Boolean::New(env->isolate(), writable) |
108 |
|
|
}; |
109 |
|
|
|
110 |
✓✓✓✓
|
13108 |
TRACE_EVENT_NESTABLE_ASYNC_END1(TRACING_CATEGORY_NODE2(net, native), |
111 |
|
|
"connect", |
112 |
|
|
req_wrap.get(), |
113 |
|
|
"status", |
114 |
|
|
status); |
115 |
|
|
|
116 |
|
11150 |
req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); |
117 |
|
11150 |
} |
118 |
|
|
|
119 |
|
|
template ConnectionWrap<PipeWrap, uv_pipe_t>::ConnectionWrap( |
120 |
|
|
Environment* env, |
121 |
|
|
Local<Object> object, |
122 |
|
|
ProviderType provider); |
123 |
|
|
|
124 |
|
|
template ConnectionWrap<TCPWrap, uv_tcp_t>::ConnectionWrap( |
125 |
|
|
Environment* env, |
126 |
|
|
Local<Object> object, |
127 |
|
|
ProviderType provider); |
128 |
|
|
|
129 |
|
|
template void ConnectionWrap<PipeWrap, uv_pipe_t>::OnConnection( |
130 |
|
|
uv_stream_t* handle, int status); |
131 |
|
|
|
132 |
|
|
template void ConnectionWrap<TCPWrap, uv_tcp_t>::OnConnection( |
133 |
|
|
uv_stream_t* handle, int status); |
134 |
|
|
|
135 |
|
|
template void ConnectionWrap<PipeWrap, uv_pipe_t>::AfterConnect( |
136 |
|
|
uv_connect_t* handle, int status); |
137 |
|
|
|
138 |
|
|
template void ConnectionWrap<TCPWrap, uv_tcp_t>::AfterConnect( |
139 |
|
|
uv_connect_t* handle, int status); |
140 |
|
|
|
141 |
|
|
|
142 |
|
|
} // namespace node |