Dart VM is broken

This commit is contained in:
Tobe O 2019-04-27 15:12:09 -04:00
parent 9d9f601fcb
commit e96d371896
12 changed files with 308 additions and 38 deletions

8
.gitignore vendored
View file

@ -21,7 +21,11 @@ doc/api/
*.js.map *.js.map
*.o *.o
#*.dylib *.dylib
#*.a *.a
*.so
*.lib *.lib
*.obj *.obj
.vscode/
.idea/

View file

@ -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 $@ $<

3
configure vendored
View file

@ -2,7 +2,8 @@
HTTP_PARSER_DIR=.dart_tool/http-parser HTTP_PARSER_DIR=.dart_tool/http-parser
if [ ! -d "$HTTP_PARSER_DIR" ] 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 $? exit $?
fi fi

View file

@ -1,4 +1,3 @@
export 'src/angel_wings.dart';
export 'src/wings_driver.dart'; export 'src/wings_driver.dart';
export 'src/wings_request.dart'; export 'src/wings_request.dart';
export 'src/wings_response.dart'; export 'src/wings_response.dart';

View file

@ -2,41 +2,50 @@
#include <iostream> #include <iostream>
#include <string.h> #include <string.h>
#include <dart_api.h> #include <dart_api.h>
#include "angel_wings.h"
// Forward declaration of ResolveName function.
Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool* auto_setup_scope);
// The name of the initialization function is the extension name followed // The name of the initialization function is the extension name followed
// by _Init. // by _Init.
DART_EXPORT Dart_Handle angel_wings_Init(Dart_Handle parent_library) { DART_EXPORT Dart_Handle angel_wings_Init(Dart_Handle parent_library)
if (Dart_IsError(parent_library)) return parent_library; {
if (Dart_IsError(parent_library))
return parent_library;
Dart_Handle result_code = Dart_Handle result_code =
Dart_SetNativeResolver(parent_library, ResolveName, NULL); 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(); return Dart_Null();
} }
Dart_Handle HandleError(Dart_Handle handle) { Dart_Handle HandleError(Dart_Handle handle)
if (Dart_IsError(handle)) Dart_PropagateError(handle); {
if (Dart_IsError(handle))
Dart_PropagateError(handle);
return handle; return handle;
} }
// Native functions get their arguments in a Dart_NativeArguments structure Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool *auto_setup_scope)
// 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) {
// If we fail, we return NULL, and Dart throws an exception. // 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; Dart_NativeFunction result = NULL;
const char* cname; const char *cname;
HandleError(Dart_StringToCString(name, &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; return result;
} }

View file

@ -1,3 +0,0 @@
import 'dart-ext:angel_wings';
void sayHello() native "SayHello";

17
lib/src/angel_wings.h Normal file
View file

@ -0,0 +1,17 @@
#ifndef ANGEL_WINGS_WINGS_H
#define ANGEL_WINGS_WINGS_H
#include <dart_api.h>
#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

160
lib/src/bind.cc Normal file
View file

@ -0,0 +1,160 @@
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#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));
}

View file

@ -1,2 +1,6 @@
include:
- lib/src
sources: sources:
- angel_wings|lib/src/angel_wings.cc - angel_wings|lib/src/angel_wings.cc
- angel_wings|lib/src/bind.cc
- angel_wings|lib/src/wings_socket.cc

1
lib/src/wings_socket.cc Normal file
View file

@ -0,0 +1 @@
#include "wings_socket.h"

View file

@ -4,11 +4,21 @@ import 'dart:isolate';
import 'dart:typed_data'; import 'dart:typed_data';
import 'dart-ext:angel_wings'; import 'dart-ext:angel_wings';
int bindWingsIPv4ServerSocket(Uint8List address, int port, bool shared, int bindWingsIPv4ServerSocket(
int backlog, bool v6Only, SendPort sendPort) native 'Dart_WingsSocket_bind'; 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 bindWingsIPv6ServerSocket(
int backlog, bool v6Only, SendPort sendPort) native 'Dart_WingsSocket_bind'; String address,
int port,
bool shared,
int backlog,
bool v6Only,
SendPort sendPort) native 'Dart_WingsSocket_bindIPV6';
int getWingsServerSocketPort(int pointer) native 'Dart_WingsSocket_getPort'; int getWingsServerSocketPort(int pointer) native 'Dart_WingsSocket_getPort';
@ -57,11 +67,11 @@ class WingsSocket extends Stream<int> {
try { try {
if (addr.type == InternetAddressType.IPv6) { if (addr.type == InternetAddressType.IPv6) {
ptr = bindWingsIPv6ServerSocket(Uint8List.fromList(addr.rawAddress), ptr = bindWingsIPv6ServerSocket(
port, shared, backlog, v6Only, recv.sendPort); addr.address, port, shared, backlog, v6Only, recv.sendPort);
} else { } else {
ptr = bindWingsIPv4ServerSocket(Uint8List.fromList(addr.rawAddress), ptr = bindWingsIPv4ServerSocket(
port, shared, backlog, v6Only, recv.sendPort); addr.address, port, shared, backlog, v6Only, recv.sendPort);
} }
return WingsSocket._(ptr, recv); return WingsSocket._(ptr, recv);

View file

@ -0,0 +1,36 @@
#ifndef WINGS_SOCKET_H
#define WINGS_SOCKET_H
#include <dart_api.h>
#include <vector>
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<Dart_Port> sendPorts;
};
extern std::vector<WingsSocket*> globalSocketList;
} // namespace wings
#endif