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

Unified Diff: runtime/bin/socket.cc

Issue 85993002: Add UDP support to dart:io (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed first round of comments Created 7 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: runtime/bin/socket.cc
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index 175d07e6a5f7a9e4608a4e177d39a3251f7c2718..7665d5ef1d5cbe55accf2afb9fa4d28672b937c1 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -25,6 +25,8 @@ int Socket::service_ports_size_ = 0;
Dart_Port* Socket::service_ports_ = NULL;
int Socket::service_ports_index_ = 0;
+// TODO(sgjesse): Make this thread local.
+unsigned int rand_r_state = 0;
static void GetSockAddr(Dart_Handle obj, RawAddr* addr) {
Dart_TypedData_Type data_type;
@@ -33,6 +35,9 @@ static void GetSockAddr(Dart_Handle obj, RawAddr* addr) {
Dart_Handle result = Dart_TypedDataAcquireData(
obj, &data_type, reinterpret_cast<void**>(&data), &len);
if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (data_type != Dart_TypedData_kUint8) {
+ Dart_PropagateError(Dart_NewApiError("Unexpected type for socket address"));
+ }
memmove(reinterpret_cast<void *>(addr), data, len);
Dart_TypedDataReleaseData(obj);
}
@@ -117,6 +122,27 @@ void FUNCTION_NAME(Socket_CreateConnect)(Dart_NativeArguments args) {
}
}
+void FUNCTION_NAME(Socket_CreateBindDatagram)(Dart_NativeArguments args) {
+ RawAddr addr;
+ GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
+ int64_t port = DartUtils::GetInt64ValueCheckRange(
+ Dart_GetNativeArgument(args, 2),
+ 0,
+ 65535);
+ intptr_t socket = Socket::CreateBindDatagram(
+ &addr,
+ port,
+ DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3)));
+ OSError error;
Anders Johnsen 2013/11/29 12:36:54 Unused?
Søren Gjesse 2013/12/12 11:38:46 Yes, removed.
+ if (socket >= 0) {
+ Socket::SetSocketIdNativeField(Dart_GetNativeArgument(args, 0), socket);
+ Dart_SetReturnValue(args, Dart_True());
+ } else {
+ OSError error;
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&error));
+ }
+}
+
void FUNCTION_NAME(Socket_Available)(Dart_NativeArguments args) {
intptr_t socket =
@@ -182,6 +208,79 @@ void FUNCTION_NAME(Socket_Read)(Dart_NativeArguments args) {
}
+void FUNCTION_NAME(Socket_RecvFrom)(Dart_NativeArguments args) {
+ static bool drop_datagrams = Dart_IsVMFlagSet("drop_datagrams");
+ intptr_t socket =
+ Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0));
+
+ // TODO(sgjesse): This needs to be 64k as that is the max UDP packet size.
+ uint8_t buffer[4096];
+ RawAddr addr;
+ intptr_t bytes_read = Socket::RecvFrom(socket, buffer, 4096, &addr);
+ Dart_Handle err;
+ if (bytes_read > 0) {
+ uint8_t* data_buffer = NULL;
+ Dart_Handle data = IOBuffer::Allocate(bytes_read, &data_buffer);
+ if (Dart_IsError(data)) Dart_PropagateError(data);
+ ASSERT(data_buffer != NULL);
+ memmove(data_buffer, buffer, bytes_read);
+
+ // Get the port and clear it in the sockaddr structure.
+ int port = SocketAddress::GetAddrPort(&addr);
+ if (addr.addr.sa_family == AF_INET) {
+ addr.in.sin_port = 0;
+ } else {
+ ASSERT(addr.addr.sa_family == AF_INET6);
+ addr.in6.sin6_port = 0;
+ }
+ // Format the address to a string using the numeric format.
+ char numeric_address[INET6_ADDRSTRLEN];
+ Socket::FormatNumericAddress(&addr, numeric_address, INET6_ADDRSTRLEN);
+
+ // Create a Datagram object with the data and sender address and port.
+ const int kNumArgs = 5;
+ Dart_Handle dart_args[kNumArgs];
+ dart_args[0] = data;
+ dart_args[1] = Dart_NewBoolean(addr.addr.sa_family == AF_INET6);
+ dart_args[2] = Dart_NewStringFromCString(numeric_address);
+ if (Dart_IsError(dart_args[2])) Dart_PropagateError(dart_args[2]);
+ int len = SocketAddress::GetAddrLength(&addr);
+ dart_args[3] = Dart_NewTypedData(Dart_TypedData_kUint8, len);
+ if (Dart_IsError(dart_args[3])) Dart_PropagateError(dart_args[3]);
+ err = Dart_ListSetAsBytes(
+ dart_args[3], 0, reinterpret_cast<uint8_t *>(&addr), len);
+ if (Dart_IsError(err)) Dart_PropagateError(err);
+ dart_args[4] = Dart_NewInteger(port);
+ if (Dart_IsError(dart_args[4])) Dart_PropagateError(dart_args[4]);
+ // TODO(sgjesse): Cache the _makeDatagram function somewhere.
+ Dart_Handle io_lib =
+ Dart_LookupLibrary(DartUtils::NewString("dart:io"));
+ if (Dart_IsError(io_lib)) Dart_PropagateError(io_lib);
+ Dart_Handle result =
+ Dart_Invoke(io_lib,
+ DartUtils::NewString("_makeDatagram"),
+ kNumArgs,
+ dart_args);
+ if (Dart_IsError(result)) Dart_PropagateError(result);
+ if (drop_datagrams) {
Anders Johnsen 2013/11/29 12:36:54 Drop earlier?
Søren Gjesse 2013/12/12 11:38:46 Done.
+ int random = rand_r(&rand_r_state);
+ if (random > (RAND_MAX / 2)) {
+ Dart_SetReturnValue(args, result);
+ } else {
+ Dart_SetReturnValue(args, Dart_Null());
+ }
+ } else {
+ Dart_SetReturnValue(args, result);
+ }
+ } else if (bytes_read == 0) {
+ Dart_SetReturnValue(args, Dart_Null());
+ } else {
+ ASSERT(bytes_read == -1);
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ }
+}
+
+
void FUNCTION_NAME(Socket_WriteList)(Dart_NativeArguments args) {
static bool short_socket_writes = Dart_IsVMFlagSet("short_socket_write");
intptr_t socket =
@@ -216,6 +315,44 @@ void FUNCTION_NAME(Socket_WriteList)(Dart_NativeArguments args) {
}
+void FUNCTION_NAME(Socket_SendTo)(Dart_NativeArguments args) {
+ intptr_t socket =
+ Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0));
+ Dart_Handle buffer_obj = Dart_GetNativeArgument(args, 1);
+ intptr_t offset =
+ DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 2));
+ intptr_t length =
+ DartUtils::GetIntptrValue(Dart_GetNativeArgument(args, 3));
+ Dart_Handle address_obj = Dart_GetNativeArgument(args, 4);
+ ASSERT(Dart_IsList(address_obj));
+ RawAddr addr;
+ GetSockAddr(address_obj, &addr);
+ int64_t port = DartUtils::GetInt64ValueCheckRange(
+ Dart_GetNativeArgument(args, 5),
+ 0,
+ 65535);
+ SocketAddress::SetAddrPort(&addr, port);
+ Dart_TypedData_Type type;
+ uint8_t* buffer = NULL;
+ intptr_t len;
+ Dart_Handle result = Dart_TypedDataAcquireData(
+ buffer_obj, &type, reinterpret_cast<void**>(&buffer), &len);
+ if (Dart_IsError(result)) Dart_PropagateError(result);
+ ASSERT((offset + length) <= len);
+ buffer += offset;
+ intptr_t bytes_written = Socket::SendTo(socket, buffer, length, addr);
+ if (bytes_written >= 0) {
+ Dart_TypedDataReleaseData(buffer_obj);
+ Dart_SetReturnValue(args, Dart_NewInteger(bytes_written));
+ } else {
+ // Extract OSError before we release data, as it may override the error.
+ OSError os_error;
+ Dart_TypedDataReleaseData(buffer_obj);
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError(&os_error));
+ }
+}
+
+
void FUNCTION_NAME(Socket_GetPort)(Dart_NativeArguments args) {
intptr_t socket =
Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0));
@@ -463,26 +600,131 @@ CObject* Socket::ListInterfacesRequest(const CObjectArray& request) {
}
+void FUNCTION_NAME(Socket_GetOption)(Dart_NativeArguments args) {
+ intptr_t socket =
+ Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0));
+ int64_t option = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 1));
+ intptr_t protocol =
+ static_cast<intptr_t>(
+ DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 2)));
+ bool ok;
+ switch (option) {
+ case 0: { // TCP_NODELAY.
+ bool enabled;
+ ok = Socket::GetNoDelay(socket, &enabled);
+ if (ok) {
+ Dart_SetReturnValue(args, enabled ? Dart_True() : Dart_False());
+ }
+ break;
+ }
+ case 1: { // IP_MULTICAST_LOOP.
+ bool enabled;
+ ok = Socket::GetMulticastLoop(socket, protocol, &enabled);
+ if (ok) {
+ Dart_SetReturnValue(args, enabled ? Dart_True() : Dart_False());
+ }
+ break;
+ }
+ case 2: { // IP_MULTICAST_TTL.
+ int value;
+ ok = Socket::GetMulticastHops(socket, protocol, &value);
+ if (ok) {
+ Dart_SetReturnValue(args, Dart_NewInteger(value));
+ }
+ break;
+ }
+ case 3: { // IP_MULTICAST_IF.
+ UNIMPLEMENTED();
+ break;
+ }
+ case 4: { // IP_BROADCAST.
+ bool enabled;
+ ok = Socket::GetBroadcast(socket, &enabled);
+ if (ok) {
+ Dart_SetReturnValue(args, enabled ? Dart_True() : Dart_False());
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+ // In case of failure the return value is not set above.
+ if (!ok) {
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ }
+}
+
+
void FUNCTION_NAME(Socket_SetOption)(Dart_NativeArguments args) {
bool result = false;
intptr_t socket =
Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0));
- Dart_Handle option_obj = Dart_GetNativeArgument(args, 1);
- int64_t option;
- Dart_Handle err = Dart_IntegerToInt64(option_obj, &option);
- if (Dart_IsError(err)) Dart_PropagateError(err);
- Dart_Handle enabled_obj = Dart_GetNativeArgument(args, 2);
- bool enabled;
- err = Dart_BooleanValue(enabled_obj, &enabled);
- if (Dart_IsError(err)) Dart_PropagateError(err);
+ int64_t option = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 1));
+ int64_t protocol = DartUtils::GetInt64ValueCheckRange(
+ Dart_GetNativeArgument(args, 2),
+ SocketAddress::TYPE_IPV4,
+ SocketAddress::TYPE_IPV6);
switch (option) {
case 0: // TCP_NODELAY.
- result = Socket::SetNoDelay(socket, enabled);
+ result = Socket::SetNoDelay(
+ socket, DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3)));
+ break;
+ case 1: // IP_MULTICAST_LOOP.
+ result = Socket::SetMulticastLoop(
+ socket,
+ protocol,
+ DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3)));
+ break;
+ case 2: // IP_MULTICAST_TTL.
+ result = Socket::SetMulticastHops(
+ socket,
+ protocol,
+ DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 3)));
+ break;
+ case 3: { // IP_MULTICAST_IF.
+ UNIMPLEMENTED();
+ break;
+ }
+ case 4: // IP_BROADCAST.
+ result = Socket::SetBroadcast(
+ socket, DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3)));
break;
default:
+ Dart_PropagateError(Dart_NewApiError("Value outside expected range"));
break;
}
- Dart_SetReturnValue(args, Dart_NewBoolean(result));
+ if (result) {
+ Dart_SetReturnValue(args, Dart_Null());
+ } else {
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ }
+}
+
+
+void FUNCTION_NAME(Socket_JoinMulticast)(Dart_NativeArguments args) {
+ intptr_t socket =
+ Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0));
+ RawAddr addr;
+ GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
+ if (Socket::JoinMulticast(socket, &addr, 0)) {
+ Dart_SetReturnValue(args, Dart_Null());
+ } else {
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ }
+}
+
+
+void FUNCTION_NAME(Socket_LeaveMulticast)(Dart_NativeArguments args) {
+ intptr_t socket =
+ Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0));
+ RawAddr addr;
+ GetSockAddr(Dart_GetNativeArgument(args, 1), &addr);
+ if (Socket::LeaveMulticast(socket, &addr, 0)) {
+ Dart_SetReturnValue(args, Dart_Null());
+ } else {
+ Dart_SetReturnValue(args, DartUtils::NewDartOSError());
+ }
}

Powered by Google App Engine
This is Rietveld 408576698