From e96d37189626ce7f9956c51e4797199ac4ce602c Mon Sep 17 00:00:00 2001 From: Tobe O Date: Sat, 27 Apr 2019 15:12:09 -0400 Subject: [PATCH] Dart VM is broken --- .gitignore | 10 +- Makefile | 32 +++++ configure | 3 +- lib/angel_wings.dart | 3 +- lib/src/angel_wings.cc | 49 ++++--- lib/src/angel_wings.dart | 3 - lib/src/angel_wings.h | 17 +++ lib/src/bind.cc | 160 +++++++++++++++++++++++ lib/src/libangel_wings.build_native.yaml | 6 +- lib/src/wings_socket.cc | 1 + lib/src/wings_socket.dart | 26 ++-- lib/src/wings_socket.h | 36 +++++ 12 files changed, 308 insertions(+), 38 deletions(-) delete mode 100644 lib/src/angel_wings.dart create mode 100644 lib/src/angel_wings.h create mode 100644 lib/src/bind.cc create mode 100644 lib/src/wings_socket.cc diff --git a/.gitignore b/.gitignore index 3d05881a..8078e48d 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,11 @@ doc/api/ *.js.map *.o -#*.dylib -#*.a +*.dylib +*.a +*.so *.lib -*.obj \ No newline at end of file +*.obj + +.vscode/ +.idea/ \ No newline at end of file diff --git a/Makefile b/Makefile index e69de29b..a746331f 100644 --- a/Makefile +++ b/Makefile @@ -0,0 +1,32 @@ +CXXFLAGS := $(CXXFLAGS) --std=c++11 -fPIC -DDART_SHARED_LIB=1 -I $(DART_SDK)/include +objects := lib/src/angel_wings.o lib/src/wings_socket.o\ +lib/src/bind.o + +.PHONY: distclean clean + +distclean: clean + rm -rf .dart_tool/http-parser + +clean: + find . -type f -name '*.o' -delete + find . -type f -name '*.obj' -delete + find . -type f -name '*.so' -delete + find . -type f -name '*.dylib' -delete + +mac: lib/src/libangel_wings.dylib + +linux: lib/src/libangel_wings.so + +lib/src/libangel_wings.dylib: $(objects) + +%.dylib: $(objects) + $(CXX) -shared -undefined dynamic_lookup -o $@ $^ + +%.so: $(objects) + $(CXX) -shared -o $@ $^ + +%.o: %.cc lib/src/angel_wings.h + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o: %.cc lib/src/angel_wings.h %.h + $(CXX) $(CXXFLAGS) -c -o $@ $< \ No newline at end of file diff --git a/configure b/configure index bbca3c43..2e5d957b 100755 --- a/configure +++ b/configure @@ -2,7 +2,8 @@ HTTP_PARSER_DIR=.dart_tool/http-parser if [ ! -d "$HTTP_PARSER_DIR" ] - git clone https://github.com/nodejs/http-parser.git "$HTTP_PARSER_DIR" +then + git clone --depth 1 https://github.com/nodejs/http-parser.git "$HTTP_PARSER_DIR" exit $? fi diff --git a/lib/angel_wings.dart b/lib/angel_wings.dart index 9bc403ed..c1cda8f7 100644 --- a/lib/angel_wings.dart +++ b/lib/angel_wings.dart @@ -1,5 +1,4 @@ -export 'src/angel_wings.dart'; export 'src/wings_driver.dart'; export 'src/wings_request.dart'; export 'src/wings_response.dart'; -export 'src/wings_socket.dart'; \ No newline at end of file +export 'src/wings_socket.dart'; diff --git a/lib/src/angel_wings.cc b/lib/src/angel_wings.cc index 3cbec736..03731301 100644 --- a/lib/src/angel_wings.cc +++ b/lib/src/angel_wings.cc @@ -2,41 +2,50 @@ #include #include #include - -// Forward declaration of ResolveName function. -Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool* auto_setup_scope); +#include "angel_wings.h" // The name of the initialization function is the extension name followed // by _Init. -DART_EXPORT Dart_Handle angel_wings_Init(Dart_Handle parent_library) { - if (Dart_IsError(parent_library)) return parent_library; +DART_EXPORT Dart_Handle angel_wings_Init(Dart_Handle parent_library) +{ + if (Dart_IsError(parent_library)) + return parent_library; Dart_Handle result_code = Dart_SetNativeResolver(parent_library, ResolveName, NULL); - if (Dart_IsError(result_code)) return result_code; + if (Dart_IsError(result_code)) + return result_code; return Dart_Null(); } -Dart_Handle HandleError(Dart_Handle handle) { - if (Dart_IsError(handle)) Dart_PropagateError(handle); - return handle; +Dart_Handle HandleError(Dart_Handle handle) +{ + if (Dart_IsError(handle)) + Dart_PropagateError(handle); + return handle; } -// Native functions get their arguments in a Dart_NativeArguments structure -// and return their results with Dart_SetReturnValue. -void SayHello(Dart_NativeArguments arguments) { - std::cout << "Hello, native world!" << std::endl; - Dart_SetReturnValue(arguments, Dart_Null()); -} - -Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool* auto_setup_scope) { +Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool *auto_setup_scope) +{ // If we fail, we return NULL, and Dart throws an exception. - if (!Dart_IsString(name)) return NULL; + if (!Dart_IsString(name)) + return NULL; Dart_NativeFunction result = NULL; - const char* cname; + const char *cname; HandleError(Dart_StringToCString(name, &cname)); - if (strcmp("SayHello", cname) == 0) result = SayHello; + if (strcmp("Dart_WingsSocket_bindIPv4", cname) == 0) + result = Dart_WingsSocket_bindIPv4; + if (strcmp("Dart_WingsSocket_bindIPv6", cname) == 0) + result = Dart_WingsSocket_bindIPv6; + if (strcmp("Dart_WingsSocket_getPort", cname) == 0) + result = Dart_WingsSocket_getPort; + if (strcmp("Dart_WingsSocket_write", cname) == 0) + result = Dart_WingsSocket_write; + if (strcmp("Dart_WingsSocket_closeDescriptor", cname) == 0) + result = Dart_WingsSocket_closeDescriptor; + if (strcmp("Dart_WingsSocket_close", cname) == 0) + result = Dart_WingsSocket_close; return result; } \ No newline at end of file diff --git a/lib/src/angel_wings.dart b/lib/src/angel_wings.dart deleted file mode 100644 index ea16d06a..00000000 --- a/lib/src/angel_wings.dart +++ /dev/null @@ -1,3 +0,0 @@ -import 'dart-ext:angel_wings'; - -void sayHello() native "SayHello"; \ No newline at end of file diff --git a/lib/src/angel_wings.h b/lib/src/angel_wings.h new file mode 100644 index 00000000..7da7dc20 --- /dev/null +++ b/lib/src/angel_wings.h @@ -0,0 +1,17 @@ +#ifndef ANGEL_WINGS_WINGS_H +#define ANGEL_WINGS_WINGS_H + +#include +#include "angel_wings.h" + +Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool *auto_setup_scope); +Dart_Handle HandleError(Dart_Handle handle); + +void Dart_WingsSocket_bindIPv4(Dart_NativeArguments arguments); +void Dart_WingsSocket_bindIPv6(Dart_NativeArguments arguments); +void Dart_WingsSocket_getPort(Dart_NativeArguments arguments); +void Dart_WingsSocket_write(Dart_NativeArguments arguments); +void Dart_WingsSocket_closeDescriptor(Dart_NativeArguments arguments); +void Dart_WingsSocket_close(Dart_NativeArguments arguments); + +#endif \ No newline at end of file diff --git a/lib/src/bind.cc b/lib/src/bind.cc new file mode 100644 index 00000000..9b0351c7 --- /dev/null +++ b/lib/src/bind.cc @@ -0,0 +1,160 @@ +#include +#include +#include +#include +#include +#include +#include "angel_wings.h" +#include "wings_socket.h" +using namespace wings; + +void getWingsSocketInfo(Dart_NativeArguments arguments, WingsSocketInfo *info); + +WingsSocket *wingsFindSocket(Dart_NativeArguments arguments, const WingsSocketInfo &info, int af); + +WingsSocket *wingsBindNewSocket(Dart_NativeArguments arguments, const WingsSocketInfo &info, int af); + +void wingsReturnBound(Dart_NativeArguments arguments, WingsSocket *socket); + +void Dart_WingsSocket_bindIPv4(Dart_NativeArguments arguments) +{ + WingsSocketInfo info; + getWingsSocketInfo(arguments, &info); + WingsSocket *socket = wingsFindSocket(arguments, info, AF_INET); + wingsReturnBound(arguments, socket); +} + +void Dart_WingsSocket_bindIPv6(Dart_NativeArguments arguments) +{ + WingsSocketInfo info; + getWingsSocketInfo(arguments, &info); + WingsSocket *socket = wingsFindSocket(arguments, info, AF_INET6); + wingsReturnBound(arguments, socket); +} + +void wingsReturnBound(Dart_NativeArguments arguments, WingsSocket *socket) +{ + Dart_Port sendPort; + HandleError(Dart_SendPortGetId(socket->getInfo().sendPortHandle, &sendPort)); + socket->incrRef(sendPort); + auto ptr = (uint64_t) socket; + Dart_Handle ptrHandle = Dart_NewIntegerFromUint64(ptr); + Dart_SetReturnValue(arguments, ptrHandle); +} + +void wingsThrowStateError(const char *msg) +{ + Dart_Handle msgHandle = Dart_NewStringFromCString(msg); + Dart_Handle emptyHandle = Dart_NewStringFromCString(""); + Dart_Handle stateErrorHandle = Dart_NewStringFromCString("StateError"); + Dart_Handle dartCoreHandle = Dart_NewStringFromCString("dart:core"); + Dart_Handle dartCore = Dart_LookupLibrary(dartCoreHandle); + Dart_Handle stateError = Dart_GetType(dartCore, stateErrorHandle, 0, nullptr); + Dart_Handle errHandle = Dart_New(stateError, emptyHandle, 1, &msgHandle); + Dart_ThrowException(errHandle); +} + +WingsSocket *wingsFindSocket(Dart_NativeArguments arguments, const WingsSocketInfo &info, int af) +{ + // Find an existing server, if any. + if (info.shared) + { + for (auto *socket : globalSocketList) + { + if (socket->getInfo() == info) + { + return socket; + } + } + } + + return wingsBindNewSocket(arguments, info, af); +} + +WingsSocket *wingsBindNewSocket(Dart_NativeArguments arguments, const WingsSocketInfo &info, int af) +{ + sockaddr *addr; + sockaddr_in v4; + sockaddr_in6 v6; + int ret; + + int sock = socket(af, SOCK_STREAM, IPPROTO_TCP); + + if (sock < 0) + { + wingsThrowStateError("Failed to create socket."); + return nullptr; + } + + int i = 1; + ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); + + if (ret < 0) + { + wingsThrowStateError("Cannot reuse address for socket."); + return nullptr; + } + + // TODO: Only on Mac??? + // ret = setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &i, sizeof(i)); + + // if (ret < 0) + // { + // wingsThrowStateError("Cannot reuse port for socket."); + // return; + // } + + if (af == AF_INET6) + { + v6.sin6_family = AF_INET6; + v6.sin6_port = htons((uint16_t)info.port); + ret = inet_pton(AF_INET6, info.address, &v6.sin6_addr.s6_addr); + if (ret >= 0) + ret = bind(sock, (const sockaddr *)&v6, sizeof(v6)); + } + else + { + v4.sin_family = AF_INET; + v4.sin_port = htons((uint16_t)info.port); + v4.sin_addr.s_addr = inet_addr(info.address); + bind(sock, (const sockaddr *)&v4, sizeof(v4)); + } + + if (ret < 0) + { + wingsThrowStateError("Failed to bind socket."); + return nullptr; + } + + if (listen(sock, SOMAXCONN) < 0) + { + wingsThrowStateError("Failed to set SOMAXCONN on bound socket."); + return nullptr; + } + + if (listen(sock, (int)info.backlog) < 0) + { + wingsThrowStateError("Failed to set backlog on bound socket."); + return nullptr; + } + + auto *out = new WingsSocket(info); + globalSocketList.push_back(out); + return out; +} + +void getWingsSocketInfo(Dart_NativeArguments arguments, WingsSocketInfo *info) +{ + Dart_Handle addressHandle = Dart_GetNativeArgument(arguments, 0); + Dart_Handle portHandle = Dart_GetNativeArgument(arguments, 1); + Dart_Handle sharedHandle = Dart_GetNativeArgument(arguments, 2); + Dart_Handle backlogHandle = Dart_GetNativeArgument(arguments, 3); + Dart_Handle v6OnlyHandle = Dart_GetNativeArgument(arguments, 4); + info->sendPortHandle = Dart_GetNativeArgument(arguments, 5); + + HandleError(Dart_StringToCString(addressHandle, &info->address)); + HandleError(Dart_IntegerToUint64(portHandle, &info->port)); + HandleError(Dart_BooleanValue(sharedHandle, &info->shared)); + HandleError(Dart_IntegerToUint64(backlogHandle, &info->backlog)); + HandleError(Dart_BooleanValue(v6OnlyHandle, &info->v6Only)); +} diff --git a/lib/src/libangel_wings.build_native.yaml b/lib/src/libangel_wings.build_native.yaml index 855e4974..f260efe8 100644 --- a/lib/src/libangel_wings.build_native.yaml +++ b/lib/src/libangel_wings.build_native.yaml @@ -1,2 +1,6 @@ +include: + - lib/src sources: - - angel_wings|lib/src/angel_wings.cc \ No newline at end of file + - angel_wings|lib/src/angel_wings.cc + - angel_wings|lib/src/bind.cc + - angel_wings|lib/src/wings_socket.cc \ No newline at end of file diff --git a/lib/src/wings_socket.cc b/lib/src/wings_socket.cc new file mode 100644 index 00000000..3c11c6bb --- /dev/null +++ b/lib/src/wings_socket.cc @@ -0,0 +1 @@ +#include "wings_socket.h" \ No newline at end of file diff --git a/lib/src/wings_socket.dart b/lib/src/wings_socket.dart index f3365dac..193c0586 100644 --- a/lib/src/wings_socket.dart +++ b/lib/src/wings_socket.dart @@ -4,11 +4,21 @@ import 'dart:isolate'; import 'dart:typed_data'; import 'dart-ext:angel_wings'; -int bindWingsIPv4ServerSocket(Uint8List address, int port, bool shared, - int backlog, bool v6Only, SendPort sendPort) native 'Dart_WingsSocket_bind'; +int bindWingsIPv4ServerSocket( + String address, + int port, + bool shared, + int backlog, + bool v6Only, + SendPort sendPort) native 'Dart_WingsSocket_bindIPv4'; -int bindWingsIPv6ServerSocket(Uint8List address, int port, bool shared, - int backlog, bool v6Only, SendPort sendPort) native 'Dart_WingsSocket_bind'; +int bindWingsIPv6ServerSocket( + String address, + int port, + bool shared, + int backlog, + bool v6Only, + SendPort sendPort) native 'Dart_WingsSocket_bindIPV6'; int getWingsServerSocketPort(int pointer) native 'Dart_WingsSocket_getPort'; @@ -57,11 +67,11 @@ class WingsSocket extends Stream { try { if (addr.type == InternetAddressType.IPv6) { - ptr = bindWingsIPv6ServerSocket(Uint8List.fromList(addr.rawAddress), - port, shared, backlog, v6Only, recv.sendPort); + ptr = bindWingsIPv6ServerSocket( + addr.address, port, shared, backlog, v6Only, recv.sendPort); } else { - ptr = bindWingsIPv4ServerSocket(Uint8List.fromList(addr.rawAddress), - port, shared, backlog, v6Only, recv.sendPort); + ptr = bindWingsIPv4ServerSocket( + addr.address, port, shared, backlog, v6Only, recv.sendPort); } return WingsSocket._(ptr, recv); diff --git a/lib/src/wings_socket.h b/lib/src/wings_socket.h index e69de29b..6c454c66 100644 --- a/lib/src/wings_socket.h +++ b/lib/src/wings_socket.h @@ -0,0 +1,36 @@ +#ifndef WINGS_SOCKET_H +#define WINGS_SOCKET_H +#include +#include + +namespace wings +{ +struct WingsSocketInfo +{ + const char *address; + uint64_t port; + bool shared; + uint64_t backlog; + bool v6Only; + Dart_Handle sendPortHandle; + bool operator==(const WingsSocketInfo& other) const; +}; + +class WingsSocket +{ + public: + explicit WingsSocket(const WingsSocketInfo& info); + void incrRef(Dart_Port port); + const WingsSocketInfo getInfo() const; + + private: + WingsSocketInfo info; + int sockfd; + int refCount; + std::vector sendPorts; +}; + +extern std::vector globalSocketList; +} // namespace wings + +#endif \ No newline at end of file