Dart VM is broken
This commit is contained in:
parent
9d9f601fcb
commit
e96d371896
12 changed files with 308 additions and 38 deletions
10
.gitignore
vendored
10
.gitignore
vendored
|
@ -21,7 +21,11 @@ doc/api/
|
|||
*.js.map
|
||||
|
||||
*.o
|
||||
#*.dylib
|
||||
#*.a
|
||||
*.dylib
|
||||
*.a
|
||||
*.so
|
||||
*.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
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -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';
|
||||
export 'src/wings_socket.dart';
|
||||
|
|
|
@ -2,41 +2,50 @@
|
|||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <dart_api.h>
|
||||
|
||||
// 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;
|
||||
}
|
|
@ -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:
|
||||
- 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-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<int> {
|
|||
|
||||
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);
|
||||
|
|
|
@ -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