OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #if !defined(DART_IO_DISABLED) | |
6 | |
7 #include "bin/sync_socket.h" | |
8 | |
9 #include "bin/dartutils.h" | |
10 #include "bin/io_buffer.h" | |
11 #include "bin/isolate_data.h" | |
12 #include "bin/lockers.h" | |
13 #include "bin/thread.h" | |
14 #include "bin/utils.h" | |
15 | |
16 #include "include/dart_api.h" | |
17 | |
18 #include "platform/globals.h" | |
19 #include "platform/utils.h" | |
20 | |
21 namespace dart { | |
22 namespace bin { | |
23 | |
24 static const int kSocketIdNativeField = 0; | |
siva
2017/04/10 22:51:46
I have one high level comment, maybe does not need
bkonyi
2017/04/11 01:30:50
They are very similar, but I think I've gotten mos
| |
25 | |
26 | |
27 void FUNCTION_NAME(SynchronousSocket_LookupRequest)(Dart_NativeArguments args) { | |
28 if (Dart_GetNativeArgumentCount(args) != 2) { | |
29 Dart_SetReturnValue( | |
30 args, DartUtils::NewDartArgumentError("Invalid argument count.")); | |
31 return; | |
32 } | |
33 | |
34 char* host = NULL; | |
35 char* peer = NULL; | |
36 int64_t type = 0; | |
37 | |
38 Dart_Handle host_arg = | |
39 Dart_GetNativeStringArgument(args, 0, reinterpret_cast<void**>(&peer)); | |
40 if (Dart_IsError(host_arg)) { | |
41 Dart_SetReturnValue( | |
42 args, DartUtils::NewDartArgumentError("Invalid value for host")); | |
zra
2017/04/10 21:39:43
host_arg is already the error that we want to prop
bkonyi
2017/04/11 01:30:50
Done.
| |
43 return; | |
44 } | |
45 | |
46 host_arg = Dart_StringToCString(host_arg, const_cast<const char**>(&host)); | |
47 if (Dart_IsError(host_arg)) { | |
48 Dart_SetReturnValue( | |
49 args, DartUtils::NewDartArgumentError("Invalid value for host")); | |
zra
2017/04/10 21:39:42
ditto
bkonyi
2017/04/11 01:30:50
Done.
| |
50 return; | |
51 } | |
52 | |
53 Dart_Handle port_error = Dart_GetNativeIntegerArgument(args, 1, &type); | |
54 if (Dart_IsError(port_error)) { | |
55 Dart_SetReturnValue( | |
56 args, DartUtils::NewDartArgumentError("Invalid value for port")); | |
zra
2017/04/10 21:39:43
ditto
bkonyi
2017/04/11 01:30:50
Done.
| |
57 return; | |
58 } | |
59 | |
60 OSError* os_error = NULL; | |
61 Dart_Handle result = NULL; | |
62 AddressList<SocketAddress>* addresses = | |
63 SocketBase::LookupAddress(host, type, &os_error); | |
64 | |
65 if (addresses == NULL) { | |
66 Dart_SetReturnValue(args, DartUtils::NewDartOSError(os_error)); | |
67 return; | |
68 } | |
69 | |
70 Dart_Handle array = Dart_NewList(addresses->count()); | |
71 DART_CHECK_VALID_AND_PROPAGATE(array); | |
zra
2017/04/10 21:39:43
This leaks 'addresses'.
Here and below, we should
bkonyi
2017/04/11 01:30:51
Done.
| |
72 | |
73 for (intptr_t i = 0; i < addresses->count(); i++) { | |
74 SocketAddress* addr = addresses->GetAt(i); | |
75 Dart_Handle entry = Dart_NewList(3); | |
76 DART_CHECK_VALID_AND_PROPAGATE(entry); | |
77 | |
78 Dart_Handle type = Dart_NewInteger(addr->GetType()); | |
79 DART_CHECK_VALID_AND_PROPAGATE(type); | |
80 Dart_ListSetAt(entry, 0, type); | |
zra
2017/04/10 21:39:42
Dart_ListSetAt returns a handle that needs to be c
bkonyi
2017/04/11 01:30:50
Done.
| |
81 | |
82 Dart_Handle as_string = Dart_NewStringFromCString(addr->as_string()); | |
83 DART_CHECK_VALID_AND_PROPAGATE(as_string); | |
84 Dart_ListSetAt(entry, 1, as_string); | |
85 | |
86 RawAddr raw = addr->addr(); | |
87 Dart_Handle data = SocketAddress::ToTypedData(raw); | |
88 DART_CHECK_VALID_AND_PROPAGATE(data); | |
89 | |
90 Dart_ListSetAt(entry, 2, data); | |
91 Dart_ListSetAt(array, i, entry); | |
92 } | |
93 result = array; | |
zra
2017/04/10 21:39:43
'result' doesn't appear to do very much. Maybe ren
bkonyi
2017/04/11 01:30:50
Done.
| |
94 delete addresses; | |
95 Dart_SetReturnValue(args, result); | |
96 return; | |
97 } | |
98 | |
99 | |
100 void FUNCTION_NAME(SynchronousSocket_CreateConnectSync)( | |
101 Dart_NativeArguments args) { | |
102 RawAddr addr; | |
103 SocketAddress::GetSockAddr(Dart_GetNativeArgument(args, 1), &addr); | |
104 Dart_Handle port_arg = Dart_GetNativeArgument(args, 2); | |
105 DART_CHECK_VALID_AND_PROPAGATE(port_arg); | |
106 int64_t port = DartUtils::GetInt64ValueCheckRange(port_arg, 0, 65535); | |
107 SocketAddress::SetAddrPort(&addr, static_cast<intptr_t>(port)); | |
108 intptr_t socket = SynchronousSocket::CreateConnect(addr); | |
109 if (socket >= 0) { | |
110 SynchronousSocket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 0), | |
111 socket); | |
112 Dart_SetReturnValue(args, Dart_True()); | |
zra
2017/04/10 21:39:43
Dart_SetBooleanReturnValue(args, true);
bkonyi
2017/04/11 01:30:50
Done.
| |
113 } else { | |
114 OSError error; | |
115 Dart_SetReturnValue(args, DartUtils::NewDartOSError(&error)); | |
116 } | |
117 } | |
118 | |
119 | |
120 void FUNCTION_NAME(SynchronousSocket_WriteList)(Dart_NativeArguments args) { | |
121 SynchronousSocket* socket = SynchronousSocket::GetSocketIdNativeField( | |
122 Dart_GetNativeArgument(args, 0)); | |
123 Dart_Handle buffer_obj = Dart_GetNativeArgument(args, 1); | |
124 if (!Dart_IsList(buffer_obj)) { | |
125 Dart_SetReturnValue(args, DartUtils::NewDartArgumentError( | |
126 "First parameter must be a List<int>")); | |
127 return; | |
128 } | |
129 intptr_t offset = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 2)); | |
130 intptr_t length = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 3)); | |
131 Dart_TypedData_Type type; | |
132 uint8_t* buffer = NULL; | |
133 intptr_t len; | |
134 Dart_Handle result = Dart_TypedDataAcquireData( | |
135 buffer_obj, &type, reinterpret_cast<void**>(&buffer), &len); | |
136 DART_CHECK_VALID_AND_PROPAGATE(result); | |
137 ASSERT((offset + length) <= len); | |
138 buffer += offset; | |
139 intptr_t bytes_written = SocketBase::Write(socket->fd(), buffer, length); | |
140 if (bytes_written >= 0) { | |
141 Dart_TypedDataReleaseData(buffer_obj); | |
142 Dart_SetReturnValue(args, Dart_NewInteger(bytes_written)); | |
zra
2017/04/10 21:39:43
Dart_SetIntegerReturnValue(args, bytes_written);
bkonyi
2017/04/11 01:30:50
Done.
| |
143 } else { | |
144 // Extract OSError before we release data, as it may override the error. | |
145 OSError os_error; | |
146 Dart_TypedDataReleaseData(buffer_obj); | |
147 Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error)); | |
148 } | |
149 } | |
150 | |
151 | |
152 void FUNCTION_NAME(SynchronousSocket_ReadList)(Dart_NativeArguments args) { | |
153 SynchronousSocket* socket = SynchronousSocket::GetSocketIdNativeField( | |
154 Dart_GetNativeArgument(args, 0)); | |
155 Dart_Handle buffer_obj = Dart_GetNativeArgument(args, 1); | |
156 if (!Dart_IsList(buffer_obj)) { | |
157 Dart_SetReturnValue(args, DartUtils::NewDartArgumentError( | |
158 "First parameter must be a List<int>")); | |
159 return; | |
160 } | |
161 intptr_t offset = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 2)); | |
162 intptr_t bytes = DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 3)); | |
163 intptr_t array_len = 0; | |
164 | |
165 Dart_Handle result = Dart_ListLength(buffer_obj, &array_len); | |
166 DART_CHECK_VALID_AND_PROPAGATE(result); | |
167 | |
zra
2017/04/10 21:39:43
Can we ASSERT something here about the list being
bkonyi
2017/04/11 01:30:50
Do you mean check to see if the offset and bytes s
zra
2017/04/11 16:19:40
Yes. See the ASSERT in a similar location in File_
| |
168 uint8_t* buffer = Dart_ScopeAllocate(bytes); | |
169 intptr_t bytes_read = SocketBase::Read(socket->fd(), buffer, bytes); | |
170 if (bytes_read >= 0) { | |
171 result = Dart_ListSetAsBytes(buffer_obj, offset, buffer, bytes_read); | |
172 if (Dart_IsError(result)) { | |
173 Dart_SetReturnValue(args, result); | |
174 } else { | |
175 Dart_SetReturnValue(args, Dart_NewInteger(bytes_read)); | |
zra
2017/04/10 21:39:42
Dart_SetIntegerReturnValue(args, bytes_read);
bkonyi
2017/04/11 01:30:50
Done.
| |
176 } | |
177 } else { | |
178 Dart_SetReturnValue(args, DartUtils::NewDartOSError()); | |
179 } | |
180 } | |
181 | |
182 | |
183 void FUNCTION_NAME(SynchronousSocket_Available)(Dart_NativeArguments args) { | |
184 SynchronousSocket* socket = SynchronousSocket::GetSocketIdNativeField( | |
185 Dart_GetNativeArgument(args, 0)); | |
186 intptr_t available = SocketBase::Available(socket->fd()); | |
187 if (available >= 0) { | |
188 Dart_SetReturnValue(args, Dart_NewInteger(available)); | |
zra
2017/04/10 21:39:43
Dart_SetIntegerReturnValue(args, available);
bkonyi
2017/04/11 01:30:50
Done.
| |
189 } else { | |
190 OSError os_error; | |
191 Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error)); | |
192 } | |
193 } | |
194 | |
195 | |
196 void FUNCTION_NAME(SynchronousSocket_CloseSync)(Dart_NativeArguments args) { | |
197 SynchronousSocket* socket = SynchronousSocket::GetSocketIdNativeField( | |
198 Dart_GetNativeArgument(args, 0)); | |
199 SocketBase::Close(socket->fd()); | |
200 socket->SetClosedFd(); | |
201 } | |
202 | |
203 | |
204 void FUNCTION_NAME(SynchronousSocket_Read)(Dart_NativeArguments args) { | |
205 SynchronousSocket* socket = SynchronousSocket::GetSocketIdNativeField( | |
206 Dart_GetNativeArgument(args, 0)); | |
207 int64_t length = 0; | |
208 if (DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 1), &length)) { | |
zra
2017/04/10 21:39:42
if (!...) {
// set error return
return;
}
the
bkonyi
2017/04/11 01:30:50
Done.
| |
209 uint8_t* buffer = NULL; | |
210 Dart_Handle result = IOBuffer::Allocate(length, &buffer); | |
211 DART_CHECK_VALID_AND_PROPAGATE(result); | |
212 ASSERT(buffer != NULL); | |
213 intptr_t bytes_read = SocketBase::Read(socket->fd(), buffer, length); | |
214 if (bytes_read == length) { | |
215 Dart_SetReturnValue(args, result); | |
216 } else if (bytes_read > 0) { | |
217 uint8_t* new_buffer = NULL; | |
218 Dart_Handle new_result = IOBuffer::Allocate(bytes_read, &new_buffer); | |
219 DART_CHECK_VALID_AND_PROPAGATE(new_result); | |
220 ASSERT(new_buffer != NULL); | |
221 memmove(new_buffer, buffer, bytes_read); | |
222 Dart_SetReturnValue(args, new_result); | |
223 } else if (bytes_read == 0) { | |
224 Dart_SetReturnValue(args, Dart_Null()); | |
zra
2017/04/10 21:39:43
I think Dart_Null() is already the default if noth
bkonyi
2017/04/11 01:30:50
Acknowledged.
| |
225 } else { | |
226 ASSERT(bytes_read == -1); | |
227 Dart_SetReturnValue(args, DartUtils::NewDartOSError()); | |
228 } | |
229 } else { | |
230 Dart_SetReturnValue(args, DartUtils::NewDartArgumentError( | |
231 "First parameter must be an integer.")); | |
232 return; | |
233 } | |
234 } | |
235 | |
236 | |
237 void FUNCTION_NAME(SynchronousSocket_ShutdownRead)(Dart_NativeArguments args) { | |
238 SynchronousSocket* socket = SynchronousSocket::GetSocketIdNativeField( | |
239 Dart_GetNativeArgument(args, 0)); | |
240 SynchronousSocket::ShutdownRead(socket->fd()); | |
241 } | |
242 | |
243 | |
244 void FUNCTION_NAME(SynchronousSocket_ShutdownWrite)(Dart_NativeArguments args) { | |
245 SynchronousSocket* socket = SynchronousSocket::GetSocketIdNativeField( | |
246 Dart_GetNativeArgument(args, 0)); | |
247 SynchronousSocket::ShutdownWrite(socket->fd()); | |
248 } | |
249 | |
250 | |
251 void FUNCTION_NAME(SynchronousSocket_GetPort)(Dart_NativeArguments args) { | |
252 SynchronousSocket* socket = SynchronousSocket::GetSocketIdNativeField( | |
253 Dart_GetNativeArgument(args, 0)); | |
254 intptr_t port = SocketBase::GetPort(socket->fd()); | |
255 if (port > 0) { | |
256 Dart_SetReturnValue(args, Dart_NewInteger(port)); | |
zra
2017/04/10 21:39:43
Dart_SetIntegerReturnValue(args, port)
bkonyi
2017/04/11 01:30:51
Done.
| |
257 } else { | |
258 Dart_SetReturnValue(args, DartUtils::NewDartOSError()); | |
259 } | |
260 } | |
261 | |
262 | |
263 void FUNCTION_NAME(SynchronousSocket_GetRemotePeer)(Dart_NativeArguments args) { | |
264 SynchronousSocket* socket = SynchronousSocket::GetSocketIdNativeField( | |
265 Dart_GetNativeArgument(args, 0)); | |
266 intptr_t port = 0; | |
267 SocketAddress* addr = SocketBase::GetRemotePeer(socket->fd(), &port); | |
268 if (addr == NULL) { | |
269 Dart_SetReturnValue(args, DartUtils::NewDartOSError()); | |
270 return; | |
271 } | |
272 Dart_Handle list = Dart_NewList(2); | |
273 DART_CHECK_VALID_AND_PROPAGATE(list); | |
zra
2017/04/10 21:39:42
This can leak 'addr'.
bkonyi
2017/04/11 01:30:50
Fixed.
| |
274 | |
275 Dart_Handle entry = Dart_NewList(3); | |
276 DART_CHECK_VALID_AND_PROPAGATE(entry); | |
277 | |
278 Dart_ListSetAt(entry, 0, Dart_NewInteger(addr->GetType())); | |
zra
2017/04/10 21:39:43
Check the result of Dart_ListSetAt()
bkonyi
2017/04/11 01:30:51
Done.
| |
279 Dart_ListSetAt(entry, 1, Dart_NewStringFromCString(addr->as_string())); | |
280 | |
281 RawAddr raw = addr->addr(); | |
282 Dart_ListSetAt(entry, 2, SocketAddress::ToTypedData(raw)); | |
283 | |
284 Dart_ListSetAt(list, 0, entry); | |
285 Dart_ListSetAt(list, 1, Dart_NewInteger(port)); | |
286 Dart_SetReturnValue(args, list); | |
287 delete addr; | |
288 } | |
289 | |
290 | |
291 static void SynchronousSocketFinalizer(void* isolate_data, | |
292 Dart_WeakPersistentHandle handle, | |
293 void* data) { | |
294 SynchronousSocket* socket = reinterpret_cast<SynchronousSocket*>(data); | |
295 if (socket->fd() >= 0) { | |
296 SocketBase::Close(socket->fd()); | |
297 socket->SetClosedFd(); | |
298 } | |
299 delete socket; | |
300 } | |
301 | |
302 | |
303 void SynchronousSocket::SetSocketIdNativeField(Dart_Handle handle, | |
304 intptr_t id) { | |
305 SynchronousSocket* socket = new SynchronousSocket(id); | |
306 Dart_Handle err = Dart_SetNativeInstanceField( | |
307 handle, kSocketIdNativeField, reinterpret_cast<intptr_t>(socket)); | |
308 DART_CHECK_VALID_AND_PROPAGATE(err); | |
zra
2017/04/10 21:39:42
This can leak 'socket'.
bkonyi
2017/04/11 01:30:51
What would be the best way to deal with this case?
zra
2017/04/11 16:19:40
There are two options:
1. Check that nothing is le
| |
309 Dart_NewWeakPersistentHandle(handle, reinterpret_cast<void*>(socket), | |
310 sizeof(SynchronousSocket), | |
311 SynchronousSocketFinalizer); | |
312 } | |
313 | |
314 | |
315 SynchronousSocket* SynchronousSocket::GetSocketIdNativeField( | |
316 Dart_Handle socket_obj) { | |
317 intptr_t id; | |
318 Dart_Handle err = | |
319 Dart_GetNativeInstanceField(socket_obj, kSocketIdNativeField, &id); | |
320 DART_CHECK_VALID_AND_PROPAGATE(err); | |
321 SynchronousSocket* socket = reinterpret_cast<SynchronousSocket*>(id); | |
322 return socket; | |
323 } | |
324 | |
325 } // namespace bin | |
326 } // namespace dart | |
327 | |
328 #endif // !defined(DART_IO_DISABLED) | |
OLD | NEW |