| Index: runtime/bin/tls_socket.cc
|
| diff --git a/runtime/bin/tls_socket.cc b/runtime/bin/tls_socket.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e16f890a5041635fdc59a914d8afa16fdeb45e3f
|
| --- /dev/null
|
| +++ b/runtime/bin/tls_socket.cc
|
| @@ -0,0 +1,185 @@
|
| +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +#include "bin/tls_socket.h"
|
| +
|
| +#include "bin/builtin.h"
|
| +#include "bin/dartutils.h"
|
| +#include "bin/thread.h"
|
| +#include "bin/utils.h"
|
| +
|
| +#include "include/dart_api.h"
|
| +
|
| +bool TlsFilter::library_initialized_ = false;
|
| +const char* TlsFilter::bufferNames[kNumBuffers] = { "readPlaintext",
|
| + "writePlaintext",
|
| + "readEncrypted",
|
| + "writeEncrypted" };
|
| +
|
| +/*
|
| + * The control flow and buffering here are complex. From the outside sources,
|
| + * here are the incoming signals and outgoing signals:
|
| + * From the Socket, onData callback when there is data.
|
| + * available() says how much is available
|
| + * readList() is safe, non-blocking, and returns amount read.
|
| + * To the Socket, onWrite when a previously blocked socket becomes available.
|
| + * writeList() is always safe, and returns amount written.
|
| + *
|
| + * To the user, we should provide the same interface: onData and onWrite.
|
| + * We can have data pushed to us by writeList().
|
| + *
|
| + * The intermediate stages should always be pushed as far as possible -
|
| + * all reads and writes should be performed until empty buffers happen or
|
| + * output buffers are full. Then we can rely on onData from the Socket or
|
| + * writeList from the user to fill empty buffers.
|
| + * If the buffers are full, we need to make sure that an onData is scheduled
|
| + * for the user, or an onWrite from the socket, comes to tell us that
|
| + * we can proceed.
|
| + *
|
| + * Because of handshakes, the write pipeline can be blocked on the read
|
| + * pipeline, or vice versa, but always some anticipated event will
|
| + * unblock something. So when the read pipeline is processed, we should try
|
| + * and advance the write pipeline if it is blocked, and vice versa, but
|
| + * not try to move the other pipeline unless it was blocked in the OpenSSL
|
| + * filter.
|
| + */
|
| +
|
| +void FUNCTION_NAME(TlsSocket_Init)(Dart_NativeArguments args) {
|
| + Dart_EnterScope();
|
| + TlsFilter* local_data = new TlsFilter;
|
| + Dart_Handle dart_this = HandleError(Dart_GetNativeArgument(args, 0));
|
| + local_data->Init(dart_this);
|
| +
|
| + Dart_SetReturnValue(args, Dart_Null());
|
| + Dart_ExitScope();
|
| +}
|
| +
|
| +void FUNCTION_NAME(TlsSocket_Connect)(Dart_NativeArguments args) {
|
| + Dart_EnterScope();
|
| + TlsFilter* local_data;
|
| +
|
| + Dart_Handle dart_this = HandleError(Dart_GetNativeArgument(args, 0));
|
| + ASSERT(Dart_IsInstance(dart_this));
|
| + int count;
|
| + HandleError(Dart_GetNativeInstanceFieldCount(dart_this, &count));
|
| + ASSERT(count == 1);
|
| + HandleError(Dart_GetNativeInstanceField(dart_this, 0,
|
| + reinterpret_cast<intptr_t*>(&local_data)));
|
| +
|
| + local_data->Connect();
|
| + Dart_SetReturnValue(args, Dart_Null());
|
| + Dart_ExitScope();
|
| +}
|
| +
|
| +void FUNCTION_NAME(TlsSocket_Destroy)(Dart_NativeArguments args) {
|
| + Dart_EnterScope();
|
| + TlsFilter* local_data;
|
| +
|
| + Dart_Handle dart_this = HandleError(Dart_GetNativeArgument(args, 0));
|
| + ASSERT(Dart_IsInstance(dart_this));
|
| + int count;
|
| + HandleError(Dart_GetNativeInstanceFieldCount(dart_this, &count));
|
| + ASSERT(count == 1);
|
| + HandleError(Dart_GetNativeInstanceField(dart_this, 0,
|
| + reinterpret_cast<intptr_t*>(&local_data)));
|
| +
|
| + local_data->Destroy();
|
| + Dart_SetReturnValue(args, Dart_Null());
|
| + Dart_ExitScope();
|
| +}
|
| +
|
| +void FUNCTION_NAME(TlsSocket_RegisterHandshakeCallbacks)(
|
| + Dart_NativeArguments args) {
|
| + Dart_EnterScope();
|
| + TlsFilter* local_data;
|
| +
|
| + Dart_Handle dart_this = HandleError(Dart_GetNativeArgument(args, 0));
|
| + Dart_Handle handshake_start = HandleError(Dart_GetNativeArgument(args, 1));
|
| + Dart_Handle handshake_finish = HandleError(Dart_GetNativeArgument(args, 2));
|
| + if (!Dart_IsInstance(dart_this) ||
|
| + !Dart_IsClosure(handshake_start) ||
|
| + !Dart_IsClosure(handshake_finish)) {
|
| + Dart_ThrowException(DartUtils::NewDartIllegalArgumentError(
|
| + "Illegal argument to RegisterHandshakeCallbacks"));
|
| + }
|
| + HandleError(Dart_GetNativeInstanceField(dart_this, 0,
|
| + reinterpret_cast<intptr_t*>(&local_data)));
|
| +
|
| + local_data->RegisterHandshakeCallbacks(handshake_start, handshake_finish);
|
| + Dart_SetReturnValue(args, Dart_Null());
|
| + Dart_ExitScope();
|
| +}
|
| +
|
| +void FUNCTION_NAME(TlsSocket_ProcessBuffer)(Dart_NativeArguments args) {
|
| + Dart_EnterScope();
|
| + TlsFilter* local_data;
|
| +
|
| + Dart_Handle dart_this = HandleError(Dart_GetNativeArgument(args, 0));
|
| + ASSERT(Dart_IsInstance(dart_this));
|
| + HandleError(Dart_GetNativeInstanceField(dart_this, 0,
|
| + reinterpret_cast<intptr_t*>(&local_data)));
|
| + Dart_Handle buffer_id_object = HandleError(Dart_GetNativeArgument(args, 1));
|
| + int64_t buffer_id = DartUtils::GetIntegerValue(buffer_id_object);
|
| + if (buffer_id < 0 || buffer_id >= TlsFilter::kNumBuffers) {
|
| + Dart_ThrowException(DartUtils::NewDartIllegalArgumentError(
|
| + "Illegal argument to ProcessBuffer"));
|
| + }
|
| +
|
| + intptr_t bytes_read = local_data->ProcessBuffer(static_cast<int>(buffer_id));
|
| + Dart_SetReturnValue(args, Dart_NewInteger(bytes_read));
|
| + Dart_ExitScope();
|
| +}
|
| +
|
| +void TlsFilter::Init(Dart_Handle dart_this) {
|
| + printf("Entering Init\n");
|
| + ASSERT(Dart_IsInstance(dart_this));
|
| + peer_ = HandleError(Dart_NewPersistentHandle(dart_this));
|
| + int count;
|
| + HandleError(Dart_GetNativeInstanceFieldCount(dart_this, &count));
|
| + ASSERT(count == 1);
|
| + HandleError(Dart_SetNativeInstanceField(dart_this, 0,
|
| + reinterpret_cast<intptr_t>(this)));
|
| + stringStart = HandleError(
|
| + Dart_NewPersistentHandle(Dart_NewString("start")));
|
| + stringLength = HandleError(
|
| + Dart_NewPersistentHandle(Dart_NewString("length")));
|
| +
|
| + InitializeBuffers();
|
| + InitializePlatformData();
|
| + printf("Exiting Init\n");
|
| +}
|
| +
|
| +void TlsFilter::InitializeBuffers() {
|
| + // Create TlsFilter buffers as ExternalUint8Array objects.
|
| + Dart_Handle dart_buffers_object = HandleError(
|
| + Dart_GetField(peer_, Dart_NewString("buffers")));
|
| + Dart_Handle dart_buffer_object = HandleError(
|
| + Dart_ListGetAt(dart_buffers_object, kReadPlaintext));
|
| + Dart_Handle tlsExternalBuffer_class = HandleError(
|
| + Dart_InstanceGetClass(dart_buffer_object));
|
| + Dart_Handle dart_buffer_size = HandleError(
|
| + Dart_GetField(tlsExternalBuffer_class, Dart_NewString("kSize")));
|
| + buffer_size = DartUtils::GetIntegerValue(dart_buffer_size);
|
| + if (buffer_size <= 0 || buffer_size > 1024 * 1024) {
|
| + Dart_ThrowException(
|
| + Dart_NewString("Invalid buffer size in _TlsExternalBuffer"));
|
| + }
|
| +
|
| + for (int i = 0; i < kNumBuffers; ++i) {
|
| + dart_buffer_objects[i] = HandleError(
|
| + Dart_NewPersistentHandle(Dart_ListGetAt(dart_buffers_object, i)));
|
| + buffers[i] = new uint8_t[buffer_size];
|
| + Dart_Handle data = HandleError(
|
| + Dart_NewExternalByteArray(buffers[i],
|
| + buffer_size, NULL, NULL));
|
| + HandleError(
|
| + Dart_SetField(dart_buffer_objects[i], Dart_NewString("data"), data));
|
| + }
|
| +}
|
| +
|
| +void TlsFilter::RegisterHandshakeCallbacks(Dart_Handle start,
|
| + Dart_Handle finish) {
|
| + handshake_start = HandleError(Dart_NewPersistentHandle(start));
|
| + handshake_finish = HandleError(Dart_NewPersistentHandle(finish));
|
| +}
|
|
|