Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(604)

Side by Side Diff: runtime/bin/sync_socket.cc

Issue 2803543006: Added synchronous socket implementation to dart:io. (Closed)
Patch Set: Addressed first round of comments Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698