Dart VM is broken
This commit is contained in:
parent
9d9f601fcb
commit
e96d371896
12 changed files with 308 additions and 38 deletions
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -21,7 +21,11 @@ doc/api/
|
||||||
*.js.map
|
*.js.map
|
||||||
|
|
||||||
*.o
|
*.o
|
||||||
#*.dylib
|
*.dylib
|
||||||
#*.a
|
*.a
|
||||||
|
*.so
|
||||||
*.lib
|
*.lib
|
||||||
*.obj
|
*.obj
|
||||||
|
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
32
Makefile
32
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 $@ $<
|
3
configure
vendored
3
configure
vendored
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -1,3 +0,0 @@
|
||||||
import 'dart-ext:angel_wings';
|
|
||||||
|
|
||||||
void sayHello() native "SayHello";
|
|
17
lib/src/angel_wings.h
Normal file
17
lib/src/angel_wings.h
Normal 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
160
lib/src/bind.cc
Normal 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));
|
||||||
|
}
|
|
@ -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
1
lib/src/wings_socket.cc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
#include "wings_socket.h"
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
Loading…
Reference in a new issue