Chromium Code Reviews| Index: runtime/bin/socket.cc |
| diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc |
| index 046bd1855ec6b105678c8ad7499dc0af6dd26d55..d555c010f85b3fb914a321475a965eff1df7681a 100644 |
| --- a/runtime/bin/socket.cc |
| +++ b/runtime/bin/socket.cc |
| @@ -3,6 +3,7 @@ |
| // BSD-style license that can be found in the LICENSE file. |
| #include "bin/io_buffer.h" |
| +#include "bin/isolate_data.h" |
| #include "bin/socket.h" |
| #include "bin/dartutils.h" |
| #include "bin/thread.h" |
| @@ -25,7 +26,6 @@ int Socket::service_ports_size_ = 0; |
| Dart_Port* Socket::service_ports_ = NULL; |
| int Socket::service_ports_index_ = 0; |
| - |
|
Anders Johnsen
2013/12/12 12:19:58
Re-add this.
Søren Gjesse
2013/12/12 15:44:39
Done.
|
| static void GetSockAddr(Dart_Handle obj, RawAddr* addr) { |
| Dart_TypedData_Type data_type; |
| uint8_t* data = NULL; |
| @@ -33,6 +33,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 +120,26 @@ void FUNCTION_NAME(Socket_CreateConnect)(Dart_NativeArguments args) { |
| } |
| } |
|
Anders Johnsen
2013/12/12 12:19:58
Double-space, and below.
Søren Gjesse
2013/12/12 15:44:39
Done.
|
| +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), |
|
Anders Johnsen
2013/12/12 12:19:58
If you extract arg 2 and 3 above, it'll be easier
Søren Gjesse
2013/12/12 15:44:39
Done.
|
| + 0, |
| + 65535); |
| + intptr_t socket = Socket::CreateBindDatagram( |
| + &addr, |
| + port, |
| + DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3))); |
| + 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 +205,79 @@ void FUNCTION_NAME(Socket_Read)(Dart_NativeArguments args) { |
| } |
| +void FUNCTION_NAME(Socket_RecvFrom)(Dart_NativeArguments args) { |
| + intptr_t socket = |
| + Socket::GetSocketIdNativeField(Dart_GetNativeArgument(args, 0)); |
| + |
| + // TODO(sgjesse): Use a MTU value here. Only the loopback adapter can |
| + // handle 64k datagrams. |
| + IsolateData* isolate_data = |
| + reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData()); |
| + if (isolate_data->udp_receive_buffer == NULL) { |
| + isolate_data->udp_receive_buffer = |
| + reinterpret_cast<uint8_t*>(malloc(65536)); |
| + } |
| + RawAddr addr; |
| + intptr_t bytes_read = |
| + Socket::RecvFrom(socket, isolate_data->udp_receive_buffer, 65536, &addr); |
| + if (bytes_read == 0) { |
| + Dart_SetReturnValue(args, Dart_Null()); |
| + return; |
| + } |
| + if (bytes_read < 0) { |
| + ASSERT(bytes_read == -1); |
| + Dart_SetReturnValue(args, DartUtils::NewDartOSError()); |
| + return; |
| + } |
| + // Datagram data read. Copy into buffer of the exact size, |
| + ASSERT(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, isolate_data->udp_receive_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]); |
| + Dart_Handle 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); |
| + Dart_SetReturnValue(args, result); |
| +} |
| + |
| + |
| void FUNCTION_NAME(Socket_WriteList)(Dart_NativeArguments args) { |
| static bool short_socket_writes = Dart_IsVMFlagSet("short_socket_write"); |
| intptr_t socket = |
| @@ -216,6 +312,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)); |
| @@ -467,26 +601,143 @@ 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 = false; |
| + 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); |
| + RawAddr interface; |
| + if (Dart_GetNativeArgument(args, 2) != Dart_Null()) { |
| + GetSockAddr(Dart_GetNativeArgument(args, 2), &interface); |
| + } |
| + int interfaceIndex = |
| + DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 3)); |
| + if (Socket::JoinMulticast(socket, &addr, &interface, interfaceIndex)) { |
| + 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); |
| + RawAddr interface; |
| + if (Dart_GetNativeArgument(args, 2) != Dart_Null()) { |
| + GetSockAddr(Dart_GetNativeArgument(args, 2), &interface); |
| + } |
| + int interfaceIndex = |
| + DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 3)); |
| + if (Socket::LeaveMulticast(socket, &addr, &interface, interfaceIndex)) { |
| + Dart_SetReturnValue(args, Dart_Null()); |
| + } else { |
| + Dart_SetReturnValue(args, DartUtils::NewDartOSError()); |
| + } |
| } |