diff --git a/packages/wings/.clang-format b/packages/wings/.clang-format new file mode 100644 index 00000000..d30c5da2 --- /dev/null +++ b/packages/wings/.clang-format @@ -0,0 +1,121 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseTab: Never +... + diff --git a/packages/wings/.gitignore b/packages/wings/.gitignore new file mode 100644 index 00000000..f2aac56f --- /dev/null +++ b/packages/wings/.gitignore @@ -0,0 +1,67 @@ +# See https://www.dartlang.org/guides/libraries/private-files + +# Files and directories created by pub +.dart_tool/ +.packages +build/ +# If you're building an application, you may want to check-in your pubspec.lock +pubspec.lock + +# Directory created by dartdoc +# If you don't generate documentation locally you can remove this line. +doc/api/ + +# Avoid committing generated Javascript files: +*.dart.js +*.info.json # Produced by the --dump-info flag. +*.js # When generated by dart2js. Don't specify *.js if your + # project includes source files written in JavaScript. +*.js_ +*.js.deps +*.js.map + +*.o +# *.dylib +*.a +# *.so +*.lib +*.obj + +.vscode/ +.idea/ +# Created by https://www.gitignore.io/api/cmake +# Edit at https://www.gitignore.io/?templates=cmake + +### CMake ### +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +### CMake Patch ### +# External projects +*-prefix/ + +# End of https://www.gitignore.io/api/cmake + +# Created by https://www.gitignore.io/api/vagrant +# Edit at https://www.gitignore.io/?templates=vagrant + +### Vagrant ### +# General +.vagrant/ + +# Log files (if you are creating logs in debug mode, uncomment this) +# *.log + +### Vagrant Patch ### +*.box + +# End of https://www.gitignore.io/api/vagrant diff --git a/packages/wings/.gitmodules b/packages/wings/.gitmodules new file mode 100644 index 00000000..6b6d60b5 --- /dev/null +++ b/packages/wings/.gitmodules @@ -0,0 +1,6 @@ +[submodule "cmake_dart_utils"] + path = cmake_dart_utils + url = https://github.com/thosakwe/cmake_dart_utils.git +[submodule "lib/src/http-parser"] + path = lib/src/http-parser + url = https://github.com/nodejs/http-parser.git diff --git a/packages/wings/CMakeLists.txt b/packages/wings/CMakeLists.txt new file mode 100644 index 00000000..4b4c1257 --- /dev/null +++ b/packages/wings/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.0) +project(angel_wings) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake_dart_utils/cmake") +find_package(Dart REQUIRED) +set(CMAKE_CXX_STANDARD 11) +add_subdirectory(lib/src) \ No newline at end of file diff --git a/packages/wings/README.md b/packages/wings/README.md new file mode 100644 index 00000000..4a80caa3 --- /dev/null +++ b/packages/wings/README.md @@ -0,0 +1,51 @@ +# wings +Native HTTP driver for Angel, for a nice speed boost. + +Not ready for production. + +## How does it work? +Typically, Angel uses the `AngelHttp` driver, which is wrapper over the `HttpServer` functionality in +`dart:io`, which in turns uses the `ServerSocket` and `Socket` functionality. This is great - Dart's standard +library comes with an HTTP server, which saves a lot of difficult in implementation. + +However, abstraction tends to come with a cost. Wings seeks to minimize abstraction entirely. Rather than +using the built-in Dart network stack, Wings' HTTP server is implemented in C++ as a Dart native extension, +and the `AngelWings` driver listens to events from the extension and converts them directly into +`RequestContext` objects, without any additional abstraction within. This reduces the amount of computation +performed on each request, and helps to minimize response latency. Sending data from the response buffer in plain +Dart surprisingly is the most expensive operation, as is revealed by the Observatory. + +By combining Dart's powerful VM with a native code server based on +[the same one used in Node.js](https://github.com/nodejs/http-parser), +`AngelWings` trims several milliseconds off every request, both saving resources and reducing +load times for high-traffic applications. + +## How can I use it? +The intended way to use `AngelWings` is via +[`package:build_native`](https://github.com/thosakwe/build_native); +however, the situation surrounding distributing native extensions is yet far from ideal, +so this package includes pre-built binaries out-of-the-box. + +Thanks to this, you can use it like any other Dart package, by installing it via Pub. + +## Brief example +Using `AngelWings` is almost identical to using `AngelHttp`; however, it does +not support SSL, and therefore should be placed behind a reverse proxy like `nginx` in production. + +```dart +main() async { + var app = new Angel(); + var wings = new AngelWings(app, shared: true, useZone: false); + + app.injectEncoders({'gzip': gzip.encoder, 'deflate': zlib.encoder}); + + app.get('/hello', 'Hello, native world! This is Angel WINGS.'); + + var fs = const LocalFileSystem(); + var vDir = new VirtualDirectory(app, fs, source: fs.directory('web')); + app.use(vDir.handleRequest); + + await wings.startServer('127.0.0.1', 3000); + print('Listening at http://${wings.address.address}:${wings.port}'); +} +``` \ No newline at end of file diff --git a/packages/wings/Vagrantfile b/packages/wings/Vagrantfile new file mode 100644 index 00000000..995ff4a3 --- /dev/null +++ b/packages/wings/Vagrantfile @@ -0,0 +1,6 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : +Vagrant.configure("2") do |config| + config.vm.box = "ubuntu/bionic64" + config.vm.provision "shell", path: "provision.sh" +end diff --git a/packages/wings/analysis_options.yaml b/packages/wings/analysis_options.yaml new file mode 100644 index 00000000..1009a0a1 --- /dev/null +++ b/packages/wings/analysis_options.yaml @@ -0,0 +1,6 @@ +include: package:pedantic/analysis_options.yaml +analyzer: + exclude: + - cmake_dart_utils/example/* + strong-mode: + implicit-casts: false \ No newline at end of file diff --git a/packages/wings/benchmark/empty.dart b/packages/wings/benchmark/empty.dart new file mode 100644 index 00000000..dcd5bc0e --- /dev/null +++ b/packages/wings/benchmark/empty.dart @@ -0,0 +1,23 @@ +import 'dart:async'; +import 'dart:io'; +import 'package:angel_framework/angel_framework.dart'; +import 'util.dart'; + +const AngelBenchmark emptyBenchmark = _EmptyBenchmark(); + +main() => runBenchmarks([emptyBenchmark]); + +class _EmptyBenchmark implements AngelBenchmark { + const _EmptyBenchmark(); + + @override + String get name => 'empty'; + + @override + FutureOr rawHandler(HttpRequest req, HttpResponse res) { + return res.close(); + } + + @override + void setupAngel(Angel app) {} +} diff --git a/packages/wings/benchmark/util.dart b/packages/wings/benchmark/util.dart new file mode 100644 index 00000000..0da16c2d --- /dev/null +++ b/packages/wings/benchmark/util.dart @@ -0,0 +1,110 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:isolate'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_framework/http.dart'; +import 'package:angel_wings/angel_wings.dart'; +import 'package:io/ansi.dart'; +import 'package:tuple/tuple.dart'; + +Future _runWrk( + {ProcessStartMode mode = ProcessStartMode.inheritStdio}) async { + return await Process.start('wrk', ['http://localhost:$testPort'], mode: mode); +} + +Future _warmUp() async { + var wrk = await _runWrk(); + await wrk.exitCode; + // await wrk.stderr.drain(); + // await wrk.stdout.drain(); +} + +Future _10s() => Future.delayed(Duration(seconds: 10)); + +const testPort = 8877; + +Future runBenchmarks(Iterable benchmarks, + {Iterable factories = const [ + // 'angel_http', + 'angel_wings', + ]}) async { + for (var benchmark in benchmarks) { + print(magenta.wrap('Entering benchmark: ${benchmark.name}')); + + // // Run dart:io + // print(lightGray.wrap('Booting dart:io server (waiting 10s)...')); + // var isolates = []; + // for (int i = 0; i < Platform.numberOfProcessors; i++) { + // isolates.add(await Isolate.spawn(_httpIsolate, benchmark)); + // } + + // await _10s(); + // print(lightGray.wrap('Warming up dart:io server...')); + // await _warmUp(); + + // stdout + // ..write(lightGray.wrap('Now running `wrk` for ')) + // ..write(cyan.wrap(benchmark.name)) + // ..writeln(lightGray.wrap(' (waiting 10s)...')); + // var wrk = await _runWrk(mode: ProcessStartMode.inheritStdio); + // await wrk.exitCode; + // isolates.forEach((i) => i.kill(priority: Isolate.immediate)); + + // Run Angel HTTP, Wings + for (var fac in factories) { + print(lightGray.wrap('Booting $fac server...')); + + var isolates = []; + for (int i = 0; i < Platform.numberOfProcessors; i++) { + isolates + .add(await Isolate.spawn(_angelIsolate, Tuple2(benchmark, fac))); + } + + await _10s(); + print(lightGray.wrap('Warming up $fac server...')); + await _warmUp(); + stdout + ..write(lightGray.wrap('Now running `wrk` for ')) + ..write(cyan.wrap(benchmark.name)) + ..writeln(lightGray.wrap('...')); + var wrk = await _runWrk(mode: ProcessStartMode.inheritStdio); + await wrk.exitCode; + } + } + + exit(0); +} + +void _httpIsolate(AngelBenchmark benchmark) { + Future(() async { + var raw = await HttpServer.bind(InternetAddress.loopbackIPv4, testPort, + shared: true); + raw.listen((r) => benchmark.rawHandler(r, r.response)); + }); +} + +void _angelIsolate(Tuple2 args) { + Future(() async { + var app = Angel(); + Driver driver; + + if (args.item2 == 'angel_http') { + driver = AngelHttp.custom(app, startShared); + } else if (args.item2 == 'angel_wings') { + driver = AngelWings.custom(app, startSharedWings); + } + + await app.configure(args.item1.setupAngel); + await driver.startServer(InternetAddress.loopbackIPv4, testPort); + }); +} + +abstract class AngelBenchmark { + const AngelBenchmark(); + + String get name; + + FutureOr setupAngel(Angel app); + + FutureOr rawHandler(HttpRequest req, HttpResponse res); +} diff --git a/packages/wings/cmake_dart_utils b/packages/wings/cmake_dart_utils new file mode 160000 index 00000000..315b1741 --- /dev/null +++ b/packages/wings/cmake_dart_utils @@ -0,0 +1 @@ +Subproject commit 315b1741fc59cd18faba32b604edf4eed0bd6e4b diff --git a/packages/wings/example/main.dart b/packages/wings/example/main.dart new file mode 100644 index 00000000..4aa16ffc --- /dev/null +++ b/packages/wings/example/main.dart @@ -0,0 +1,34 @@ +import 'dart:io'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_static/angel_static.dart'; +import 'package:angel_wings/angel_wings.dart'; +import 'package:file/local.dart'; +import 'package:logging/logging.dart'; +import 'package:pretty_logging/pretty_logging.dart'; + +main() async { + hierarchicalLoggingEnabled = true; + + var logger = Logger.detached('wings') + ..level = Level.ALL + ..onRecord.listen(prettyLog); + var app = Angel(logger: logger); + var wings = AngelWings(app); + var fs = LocalFileSystem(); + var vDir = CachingVirtualDirectory(app, fs, + source: fs.currentDirectory, allowDirectoryListing: true); + + app.mimeTypeResolver.addExtension('yaml', 'text/x-yaml'); + + app.get('/', (req, res) => 'WINGS!!!'); + app.post('/', (req, res) async { + await req.parseBody(); + return req.bodyAsMap; + }); + + app.fallback(vDir.handleRequest); + app.fallback((req, res) => throw AngelHttpException.notFound()); + + await wings.startServer(InternetAddress.loopbackIPv4, 3000); + print('Listening at ${wings.uri}'); +} diff --git a/packages/wings/example/shared.dart b/packages/wings/example/shared.dart new file mode 100644 index 00000000..2b9f6ee5 --- /dev/null +++ b/packages/wings/example/shared.dart @@ -0,0 +1,22 @@ +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_wings/angel_wings.dart'; + +main() async { + var app = Angel(); + var wings1 = AngelWings.custom(app, startSharedWings); + var wings2 = AngelWings.custom(app, startSharedWings); + var wings3 = AngelWings.custom(app, startSharedWings); + var wings4 = AngelWings.custom(app, startSharedWings); + await wings1.startServer('127.0.0.1', 3000); + await wings2.startServer('127.0.0.1', 3000); + await wings3.startServer('127.0.0.1', 3000); + await wings4.startServer('127.0.0.1', 3000); + print(wings1.uri); + print(wings2.uri); + print(wings3.uri); + print(wings4.uri); + await wings1.close(); + await wings2.close(); + await wings3.close(); + await wings4.close(); +} diff --git a/packages/wings/example/socket.dart b/packages/wings/example/socket.dart new file mode 100644 index 00000000..5c827772 --- /dev/null +++ b/packages/wings/example/socket.dart @@ -0,0 +1,27 @@ +import 'dart:convert'; +import 'dart:typed_data'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_wings/angel_wings.dart'; + +main() async { + var app = Angel(); + var socket = await WingsSocket.bind('127.0.0.1', 3000); + print('Listening at http://localhost:3000'); + + await for (var fd in socket) { + var response = ''' +HTTP/1.1 200 Not Found\r +Date: Fri, 31 Dec 1999 23:59:59 GMT\r +server: wings-test\r\n\r +Nope, nothing's here! +\r\n\r +'''; + var bytes = utf8.encode(response); + var data = Uint8List.fromList(bytes); + var rq = await WingsRequestContext.from(app, fd); + print('Yay: $rq'); + print(rq.headers); + writeToNativeSocket(fd.fileDescriptor, data); + closeNativeSocketDescriptor(fd.fileDescriptor); + } +} diff --git a/packages/wings/lib/angel_wings.dart b/packages/wings/lib/angel_wings.dart new file mode 100644 index 00000000..c1cda8f7 --- /dev/null +++ b/packages/wings/lib/angel_wings.dart @@ -0,0 +1,4 @@ +export 'src/wings_driver.dart'; +export 'src/wings_request.dart'; +export 'src/wings_response.dart'; +export 'src/wings_socket.dart'; diff --git a/packages/wings/lib/src/CMakeLists.txt b/packages/wings/lib/src/CMakeLists.txt new file mode 100644 index 00000000..758fce7d --- /dev/null +++ b/packages/wings/lib/src/CMakeLists.txt @@ -0,0 +1,8 @@ +include_directories("${CMAKE_CURRENT_LIST_DIR}") +add_dart_native_extension(angel_wings + http-parser/http_parser.c + angel_wings.h angel_wings.cc + bind.cc http.cc wings_socket.cc + util.cc) +install(TARGETS angel_wings LIBRARY DESTINATION "${CMAKE_CURRENT_LIST_DIR}") +install(TARGETS angel_wings LIBRARY DESTINATION "${CMAKE_CURRENT_LIST_DIR}/../..") diff --git a/packages/wings/lib/src/angel_wings.cc b/packages/wings/lib/src/angel_wings.cc new file mode 100644 index 00000000..74d3a8ef --- /dev/null +++ b/packages/wings/lib/src/angel_wings.cc @@ -0,0 +1,55 @@ +#include "angel_wings.h" +#include +#include +#include +#include + +// 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_Handle result_code = + Dart_SetNativeResolver(parent_library, ResolveName, NULL); + 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_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; + Dart_NativeFunction result = NULL; + const char *cname; + HandleError(Dart_StringToCString(name, &cname)); + + 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_getAddress", cname) == 0) + result = Dart_WingsSocket_getAddress; + 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; + if (strcmp("Dart_WingsSocket_listen", cname) == 0) + result = Dart_WingsSocket_listen; + if (strcmp("Dart_WingsSocket_parseHttp", cname) == 0) + result = Dart_WingsSocket_parseHttp; + return result; +} \ No newline at end of file diff --git a/packages/wings/lib/src/angel_wings.h b/packages/wings/lib/src/angel_wings.h new file mode 100644 index 00000000..3aeda0b7 --- /dev/null +++ b/packages/wings/lib/src/angel_wings.h @@ -0,0 +1,25 @@ +#ifndef ANGEL_WINGS_WINGS_H +#define ANGEL_WINGS_WINGS_H + +#include "angel_wings.h" +#include +#include + +Dart_NativeFunction ResolveName(Dart_Handle name, int argc, + bool *auto_setup_scope); +Dart_Handle HandleError(Dart_Handle handle); + +void wingsThrowError(const char *msg, const char *lib = "dart:core", + const char *name = "StateError", int n = -1); +void Dart_WingsSocket_bindIPv4(Dart_NativeArguments arguments); +void Dart_WingsSocket_bindIPv6(Dart_NativeArguments arguments); +void Dart_WingsSocket_getAddress(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); +void Dart_WingsSocket_listen(Dart_NativeArguments arguments); +void Dart_WingsSocket_parseHttp(Dart_NativeArguments arguments); +void wingsHttpCallback(Dart_Port dest_port_id, Dart_CObject *message); + +#endif \ No newline at end of file diff --git a/packages/wings/lib/src/bind.cc b/packages/wings/lib/src/bind.cc new file mode 100644 index 00000000..26d90781 --- /dev/null +++ b/packages/wings/lib/src/bind.cc @@ -0,0 +1,161 @@ +#include "angel_wings.h" +#include "wings_socket.h" +#include +#include +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_bind(sa_family_t af, Dart_NativeArguments arguments) { + WingsSocketInfo info; + getWingsSocketInfo(arguments, &info); + WingsSocket *socket = wingsFindSocket(arguments, info, af); + wingsReturnBound(arguments, socket); +} + +void Dart_WingsSocket_bindIPv4(Dart_NativeArguments arguments) { + Dart_WingsSocket_bind(AF_INET, arguments); +} + +void Dart_WingsSocket_bindIPv6(Dart_NativeArguments arguments) { + Dart_WingsSocket_bind(AF_INET6, arguments); +} + +void wingsReturnBound(Dart_NativeArguments arguments, WingsSocket *socket) { + Dart_Port sendPort; + HandleError( + Dart_SendPortGetId(Dart_GetNativeArgument(arguments, 5), &sendPort)); + socket->incrRef(sendPort); + auto ptr = (uint64_t)socket; + Dart_Handle ptrHandle = Dart_NewIntegerFromUint64(ptr); + Dart_SetReturnValue(arguments, ptrHandle); +} + +WingsSocket *wingsFindSocket(Dart_NativeArguments arguments, + const WingsSocketInfo &info, int af) { + // Find an existing server, if any. + if (info.shared) { + // std::cout << info.address << std::endl; + // std::cout << globalSocketList.size() << std::endl; + for (auto *socket : globalSocketList) { + if (info.equals(socket->getInfo())) { + 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) { + wingsThrowError("Failed to create socket."); + return nullptr; + } + + int i = 1; + ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); + + if (ret < 0) { + wingsThrowError("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) { + wingsThrowError("Failed to bind socket."); + return nullptr; + } + + if (listen(sock, SOMAXCONN) < 0) { + wingsThrowError("Failed to set SOMAXCONN on bound socket."); + return nullptr; + } + + if (listen(sock, (int)info.backlog) < 0) { + wingsThrowError("Failed to set backlog on bound socket."); + return nullptr; + } + + if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) { + wingsThrowError("Failed to make socket non-blocking."); + return nullptr; + } + + auto *out = new WingsSocket(af, sock, 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)); +} + +void wingsThrowError(const char *msg, const char *lib, const char *name, + int n) { + Dart_Handle msgHandle = Dart_NewStringFromCString(msg); + Dart_Handle emptyHandle = Dart_NewStringFromCString(""); + Dart_Handle stateErrorHandle = Dart_NewStringFromCString(name); + Dart_Handle dartCoreHandle = Dart_NewStringFromCString(lib); + Dart_Handle dartCore = Dart_LookupLibrary(dartCoreHandle); + Dart_Handle stateError = Dart_GetType(dartCore, stateErrorHandle, 0, nullptr); + + std::vector args; + args.push_back(msgHandle); + + if (n > -1) { + args.push_back(Dart_NewInteger(n)); + } + + Dart_Handle errHandle = + Dart_New(stateError, emptyHandle, args.size(), args.data()); + Dart_ThrowException(errHandle); +} \ No newline at end of file diff --git a/packages/wings/lib/src/http-parser b/packages/wings/lib/src/http-parser new file mode 160000 index 00000000..28f3c35c --- /dev/null +++ b/packages/wings/lib/src/http-parser @@ -0,0 +1 @@ +Subproject commit 28f3c35c215ffbe0241685901338fad484660454 diff --git a/packages/wings/lib/src/http.cc b/packages/wings/lib/src/http.cc new file mode 100644 index 00000000..a9fe7183 --- /dev/null +++ b/packages/wings/lib/src/http.cc @@ -0,0 +1,175 @@ +#include + +#include "angel_wings.h" +#include "wings_socket.h" +#include +#include +using namespace wings; + +void Dart_WingsSocket_parseHttp(Dart_NativeArguments arguments) { + Dart_Port service_port = + Dart_NewNativePort("WingsHttpCallback", &wingsHttpCallback, true); + Dart_Handle send_port = Dart_NewSendPort(service_port); + Dart_SetReturnValue(arguments, send_port); +} + +struct wingsHttp { + Dart_Port port; + std::string lastHeader; +}; + +void wingsHttpCallback(Dart_Port dest_port_id, Dart_CObject *message) { + int64_t fd = -1; + Dart_Port outPort = message->value.as_array.values[0]->value.as_send_port.id; + Dart_CObject *fdArg = message->value.as_array.values[1]; + + wingsHttp httpData = {outPort}; + +#define theStruct (*((wingsHttp *)parser->data)) +#define thePort theStruct.port +#define sendInt(n) \ + { \ + Dart_CObject obj; \ + obj.type = Dart_CObject_kInt64; \ + obj.value.as_int64 = (n); \ + Dart_PostCObject(thePort, &obj); \ + } +#define sendString(n) \ + if (length > 0) { \ + Dart_CObject typeObj; \ + typeObj.type = Dart_CObject_kInt32; \ + typeObj.value.as_int32 = (n); \ + std::string str(at, length); \ + Dart_CObject strObj; \ + strObj.type = Dart_CObject_kString; \ + strObj.value.as_string = (char *)str.c_str(); \ + Dart_CObject *values[2] = {&typeObj, &strObj}; \ + Dart_CObject out; \ + out.type = Dart_CObject_kArray; \ + out.value.as_array.length = 2; \ + out.value.as_array.values = values; \ + Dart_PostCObject(thePort, &out); \ + } + + if (fdArg->type == Dart_CObject_kInt32) { + fd = (int64_t)fdArg->value.as_int32; + } else { + fd = fdArg->value.as_int64; + } + + if (fd != -1) { + http_parser_settings settings; + + settings.on_message_begin = [](http_parser *parser) { return 0; }; + + settings.on_headers_complete = [](http_parser *parser) { + Dart_CObject type; + type.type = Dart_CObject_kInt32; + type.value.as_int32 = 2; + Dart_CObject value; + value.type = Dart_CObject_kInt32; + value.value.as_int32 = parser->method; + Dart_CObject *values[2] = {&type, &value}; + Dart_CObject out; + out.type = Dart_CObject_kArray; + out.value.as_array.length = 2; + out.value.as_array.values = values; + Dart_PostCObject(thePort, &out); + sendInt(100); + return 0; + }; + + settings.on_message_complete = [](http_parser *parser) { + sendInt(200); + return 0; + }; + + settings.on_chunk_complete = [](http_parser *parser) { return 0; }; + + settings.on_chunk_header = [](http_parser *parser) { return 0; }; + + settings.on_url = [](http_parser *parser, const char *at, size_t length) { + sendString(0); + return 0; + }; + + settings.on_header_field = [](http_parser *parser, const char *at, + size_t length) { + theStruct.lastHeader = std::string(at, length); + return 0; + }; + + settings.on_header_value = [](http_parser *parser, const char *at, + size_t length) { + if (!theStruct.lastHeader.empty()) { + std::string vStr(at, length); + Dart_CObject type; + type.type = Dart_CObject_kInt32; + type.value.as_int32 = 1; + Dart_CObject name; + name.type = Dart_CObject_kString; + name.value.as_string = (char *)theStruct.lastHeader.c_str(); + Dart_CObject value; + value.type = Dart_CObject_kString; + value.value.as_string = (char *)vStr.c_str(); + Dart_CObject *values[3] = {&type, &name, &value}; + Dart_CObject out; + out.type = Dart_CObject_kArray; + out.value.as_array.length = 3; + out.value.as_array.values = values; + Dart_PostCObject(thePort, &out); + theStruct.lastHeader.clear(); + } + return 0; + }; + + settings.on_body = [](http_parser *parser, const char *at, size_t length) { + Dart_CObject obj; + obj.type = Dart_CObject_kTypedData; + obj.value.as_typed_data.type = Dart_TypedData_kUint8; + obj.value.as_typed_data.length = length; + obj.value.as_typed_data.values = (uint8_t *)at; + Dart_PostCObject(thePort, &obj); + return 0; + }; + + size_t len = 80 * 1024, nparsed = 0; + char buf[len]; + ssize_t recved = 0; + memset(buf, 0, sizeof(buf)); + // http_parser parser; + auto *parser = (http_parser *)malloc(sizeof(http_parser)); + http_parser_init(parser, HTTP_BOTH); + parser->data = &httpData; + + while ((recved = recv(fd, buf, len, 0)) >= 0) { + if (false) // (isUpgrade) + { + // send_string(&parser, buf, (size_t)recved, 7, true); + } else { + /* Start up / continue the parser. + * Note we pass recved==0 to signal that EOF has been received. + */ + nparsed = http_parser_execute(parser, &settings, buf, recved); + + if (nparsed != recved) { + // TODO: End it...! + } else if (recved == 0) { + break; + } + + // if ((isUpgrade = parser.upgrade) == 1) + // { + // send_notification(&parser, 6); + // } + // else if (nparsed != recved) + // { + // close(rq->sock); + // return; + // } + } + + // memset(buf, 0, len); + } + } +} \ No newline at end of file diff --git a/packages/wings/lib/src/libangel_wings.dylib b/packages/wings/lib/src/libangel_wings.dylib new file mode 100755 index 00000000..fbcfc381 Binary files /dev/null and b/packages/wings/lib/src/libangel_wings.dylib differ diff --git a/packages/wings/lib/src/libangel_wings.so b/packages/wings/lib/src/libangel_wings.so new file mode 100644 index 00000000..92b8f107 Binary files /dev/null and b/packages/wings/lib/src/libangel_wings.so differ diff --git a/packages/wings/lib/src/util.cc b/packages/wings/lib/src/util.cc new file mode 100644 index 00000000..227f4e24 --- /dev/null +++ b/packages/wings/lib/src/util.cc @@ -0,0 +1,146 @@ +#include + +#include "angel_wings.h" +#include "wings_socket.h" +#include +#include +using namespace wings; + +void Dart_WingsSocket_listen(Dart_NativeArguments arguments) { + uint64_t ptr; + Dart_Handle pointerHandle = Dart_GetNativeArgument(arguments, 0); + HandleError(Dart_IntegerToUint64(pointerHandle, &ptr)); + + auto *socket = (WingsSocket *)ptr; + socket->start(arguments); +} + +struct wingsSockName { + sa_family_t family; + sockaddr_in v4; + sockaddr_in6 v6; + + struct sockaddr *ptr() const { + if (family == AF_INET6) { + return (sockaddr *)&v6; + } else { + return (sockaddr *)&v4; + } + } + + void *addrPtr() const { + if (family == AF_INET6) { + return (void *)&v6.sin6_addr; + } else { + return (void *)&v4.sin_addr; + } + } + + socklen_t length() const { + if (family == AF_INET6) { + return sizeof(v6); + } else { + return sizeof(v4); + } + } +}; + +void wingsThrowOSError() { + wingsThrowError(strerror(errno), "dart:io", "OSError", errno); +} + +bool wingsReadSocket(Dart_NativeArguments arguments, wingsSockName *out) { + uint64_t ptr; + Dart_Handle pointerHandle = Dart_GetNativeArgument(arguments, 0); + HandleError(Dart_IntegerToUint64(pointerHandle, &ptr)); + + auto *socket = (WingsSocket *)ptr; + int fd = socket->getFD(); + + socklen_t len; + out->family = socket->getFamily(); + len = out->length(); + + int result; + + // result = connect(fd, out->ptr(), len); + + // if (result < 0) + // { + // wingsThrowOSError(); + // return false; + // } + + result = getsockname(fd, out->ptr(), &len); + + if (result == -1) { + wingsThrowOSError(); + return false; + } + + return true; +} + +void Dart_WingsSocket_getAddress(Dart_NativeArguments arguments) { + wingsSockName sock; + if (wingsReadSocket(arguments, &sock)) { + char addrBuf[INET6_ADDRSTRLEN + 1] = {0}; + + auto *result = + inet_ntop(sock.family, sock.addrPtr(), addrBuf, sock.length()); + + if (result == NULL) { + wingsThrowOSError(); + } + + Dart_Handle outHandle = Dart_NewStringFromCString(addrBuf); + Dart_SetReturnValue(arguments, outHandle); + } +} + +void Dart_WingsSocket_getPort(Dart_NativeArguments arguments) { + wingsSockName sock; + if (wingsReadSocket(arguments, &sock)) { + Dart_Handle outHandle; + + if (sock.family == AF_INET6) { + outHandle = Dart_NewIntegerFromUint64(ntohs(sock.v6.sin6_port)); + } else { + outHandle = Dart_NewIntegerFromUint64(ntohs(sock.v4.sin_port)); + } + + Dart_SetReturnValue(arguments, outHandle); + } +} + +void Dart_WingsSocket_write(Dart_NativeArguments arguments) { + int64_t fd; + void *data; + Dart_TypedData_Type type; + intptr_t len; + Dart_Handle fdHandle = Dart_GetNativeArgument(arguments, 0); + Dart_Handle dataHandle = Dart_GetNativeArgument(arguments, 1); + HandleError(Dart_IntegerToInt64(fdHandle, &fd)); + HandleError(Dart_TypedDataAcquireData(dataHandle, &type, &data, &len)); + write(fd, data, len); + HandleError(Dart_TypedDataReleaseData(dataHandle)); +} + +void Dart_WingsSocket_closeDescriptor(Dart_NativeArguments arguments) { + int64_t fd; + Dart_Handle fdHandle = Dart_GetNativeArgument(arguments, 0); + HandleError(Dart_IntegerToInt64(fdHandle, &fd)); + close(fd); +} + +void Dart_WingsSocket_close(Dart_NativeArguments arguments) { + Dart_Port port; + uint64_t ptr; + Dart_Handle pointerHandle = Dart_GetNativeArgument(arguments, 0); + Dart_Handle sendPortHandle = Dart_GetNativeArgument(arguments, 1); + HandleError(Dart_IntegerToUint64(pointerHandle, &ptr)); + HandleError(Dart_SendPortGetId(sendPortHandle, &port)); + + auto *socket = (WingsSocket *)ptr; + socket->decrRef(port); +} \ No newline at end of file diff --git a/packages/wings/lib/src/wings_driver.dart b/packages/wings/lib/src/wings_driver.dart new file mode 100644 index 00000000..20a2eb5b --- /dev/null +++ b/packages/wings/lib/src/wings_driver.dart @@ -0,0 +1,98 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io' show Cookie; +import 'dart:typed_data'; +import 'package:angel_framework/angel_framework.dart'; +import 'wings_request.dart'; +import 'wings_response.dart'; +import 'wings_socket.dart'; + +Future startSharedWings(dynamic addr, int port) { + return WingsSocket.bind(addr, port, shared: true); +} + +class AngelWings extends Driver { + factory AngelWings(Angel app) { + return AngelWings.custom(app, WingsSocket.bind); + } + + AngelWings.custom( + Angel app, Future Function(dynamic, int) serverGenerator) + : super(app, serverGenerator); + + @override + void addCookies(int response, Iterable cookies) { + for (var cookie in cookies) { + setHeader(response, 'set-cookie', cookie.toString()); + } + } + + @override + Future close() async { + await server?.close(); + return super.close(); + } + + @override + Future closeResponse(int response) { + closeNativeSocketDescriptor(response); + return Future.value(); + } + + @override + Future createRequestContext( + WingsClientSocket request, int response) { + return WingsRequestContext.from(app, request); + } + + @override + Future createResponseContext( + WingsClientSocket request, int response, + [WingsRequestContext correspondingRequest]) { + return Future.value(WingsResponseContext( + app, request.fileDescriptor, correspondingRequest)); + } + + @override + Stream createResponseStreamFromRawRequest(WingsClientSocket request) { + return Stream.fromIterable([request.fileDescriptor]); + } + + @override + void setChunkedEncoding(int response, bool value) { + // TODO: implement setChunkedEncoding + } + + @override + void setContentLength(int response, int length) { + writeStringToResponse(response, 'content-length: $length\r\n'); + } + + @override + void setHeader(int response, String key, String value) { + writeStringToResponse(response, '$key: $value\r\n'); + } + + @override + void setStatusCode(int response, int value) { + // HTTP-Version SP Status-Code SP Reason-Phrase CRLF + writeStringToResponse(response, 'HTTP/1.1 $value\r\n'); + } + + @override + Uri get uri { + return Uri(scheme: 'http', host: server.address.address, port: server.port); + } + + @override + void writeStringToResponse(int response, String value) { + writeToResponse(response, utf8.encode(value)); + } + + @override + void writeToResponse(int response, List data) { + var buf = data is Uint8List ? data : Uint8List.fromList(data); + writeToNativeSocket(response, buf); + } +} diff --git a/packages/wings/lib/src/wings_request.dart b/packages/wings/lib/src/wings_request.dart new file mode 100644 index 00000000..bb066028 --- /dev/null +++ b/packages/wings/lib/src/wings_request.dart @@ -0,0 +1,215 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:isolate'; +import 'dart:typed_data'; +import 'package:angel_container/angel_container.dart'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:mock_request/mock_request.dart'; +import 'wings_socket.dart'; + +enum _ParseState { method, url, headerField, headerValue, body } + +final RegExp _straySlashes = RegExp(r'(^/+)|(/+$)'); + +class WingsRequestContext extends RequestContext { + final WingsClientSocket rawRequest; + final Container container; + + final StreamController> _body = StreamController(); + List _cookies, __cookies; + final LockableMockHttpHeaders _headers = LockableMockHttpHeaders(); + final RawReceivePort _recv; + InternetAddress _remoteAddress; + String _method, _override, _path; + Uri _uri; + + @override + Angel app; + + WingsRequestContext._(this.app, this.rawRequest, this._recv) + : container = app.container.createChild(); + + Future close() async { + await _body.close(); + _recv.close(); + await super.close(); + } + + static const int DELETE = 0, + GET = 1, + HEAD = 2, + POST = 3, + PUT = 4, + CONNECT = 5, + OPTIONS = 6, + TRACE = 7, + COPY = 8, + LOCK = 9, + MKCOL = 10, + MOVE = 11, + PROPFIND = 12, + PROPPATCH = 13, + SEARCH = 14, + UNLOCK = 15, + BIND = 16, + REBIND = 17, + UNBIND = 18, + ACL = 19, + REPORT = 20, + MKACTIVITY = 21, + CHECKOUT = 22, + MERGE = 23, + MSEARCH = 24, + NOTIFY = 25, + SUBSCRIBE = 26, + UNSUBSCRIBE = 27, + PATCH = 28, + PURGE = 29, + MKCALENDAR = 30, + LINK = 31, + UNLINK = 32, + SOURCE = 33; + + static String methodToString(int method) { + switch (method) { + case DELETE: + return 'DELETE'; + case GET: + return 'GET'; + case HEAD: + return 'HEAD'; + case POST: + return 'POST'; + case PUT: + return 'PUT'; + case CONNECT: + return 'CONNECT'; + case OPTIONS: + return 'OPTIONS'; + case PATCH: + return 'PATCH'; + case PURGE: + return 'PURGE'; + default: + throw ArgumentError('Unknown method $method.'); + } + } + + static Future from(Angel app, WingsClientSocket socket) { + // var state = _ParseState.url; + var c = Completer(); + var recv = RawReceivePort(); + var rq = WingsRequestContext._(app, socket, recv); + rq._remoteAddress = socket.remoteAddress; + var ct = StreamController(); + recv.handler = ct.add; + recv.handler = (ee) { + if (ee is Uint8List) { + if (!rq._body.isClosed) rq._body.add(ee); + } else if (ee is List) { + var type = ee[0] as int; + + if (type == 2) { + rq._method = methodToString(ee[1] as int); + } else { + var value = ee[1] as String; + + if (type == 0) { + rq._uri = Uri.parse(value); + var path = rq._uri.path.replaceAll(_straySlashes, ''); + if (path.isEmpty) path = '/'; + rq._path = path; + } else if (type == 1) { + var k = value, v = ee[2] as String; + if (k == 'cookie') { + rq.__cookies.add(Cookie.fromSetCookieValue(v)); + } else { + rq._headers.add(k, v); + } + } else { + // print("h: $ee');"); + } + } + } else if (ee == 100) { + // Headers done, just listen for body. + c.complete(rq); + } else if (ee == 200) { + // Message complete. + rq._body.close(); + } + // if (state == _ParseState.url) { + // rq._uri = Uri.parse(e as String); + // var path = rq._uri.path.replaceAll(_straySlashes, ''); + // if (path.isEmpty) path = '/'; + // rq._path = path; + // state = _ParseState.headerField; + // } else if (state == _ParseState.headerField) { + // if (e == 0) { + // state = _ParseState.method; + // } else { + // lastHeader = e as String; //Uri.decodeFull(e as String); + // state = _ParseState.headerValue; + // } + // } else if (state == _ParseState.headerValue) { + // if (e == 0) { + // state = _ParseState.method; + // } else { + // var value = e as String; //Uri.decodeFull(e as String); + // if (lastHeader != null) { + // if (lastHeader == 'cookie') { + // rq.__cookies.add(Cookie.fromSetCookieValue(value)); + // } else { + // rq._headers.add(lastHeader, value); + // } + // lastHeader = null; + // } + // } + // state = _ParseState.headerField; + // } else if (state == _ParseState.method) { + // rq._method = methodToString(e as int); + // state = _ParseState.body; + // c.complete(rq); + // } else if (state == _ParseState.body) { + // if (e == 1) { + // rq._body.close(); + // } else { + // rq._body.add(e as List); + // } + // } + }; + wingsParseHttp().send([recv.sendPort, socket.fileDescriptor]); + return c.future; + } + + @override + Stream> get body => _body.stream; + + @override + List get cookies => _cookies ??= List.unmodifiable(__cookies); + + @override + HttpHeaders get headers => _headers; + + @override + String get hostname => headers.value('host'); + + @override + String get method => _override ??= + (headers.value('x-http-method-override')?.toUpperCase() ?? _method); + + @override + String get originalMethod => _method; + + @override + String get path => _path; + + @override + InternetAddress get remoteAddress => _remoteAddress; + + @override + // TODO: implement session + HttpSession get session => null; + + @override + Uri get uri => _uri; +} diff --git a/packages/wings/lib/src/wings_response.dart b/packages/wings/lib/src/wings_response.dart new file mode 100644 index 00000000..cdb22099 --- /dev/null +++ b/packages/wings/lib/src/wings_response.dart @@ -0,0 +1,215 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:charcode/ascii.dart'; +import 'wings_request.dart'; +import 'wings_socket.dart'; + +class WingsResponseContext extends ResponseContext { + @override + final Angel app; + + @override + final WingsRequestContext correspondingRequest; + + LockableBytesBuilder _buffer; + + @override + final int rawResponse; + + bool _isDetached = false, _isClosed = false, _streamInitialized = false; + + WingsResponseContext(this.app, this.rawResponse, [this.correspondingRequest]); + + Iterable __allowedEncodings; + + Iterable get _allowedEncodings { + return __allowedEncodings ??= correspondingRequest.headers + .value('accept-encoding') + ?.split(',') + ?.map((s) => s.trim()) + ?.where((s) => s.isNotEmpty) + ?.map((str) { + // Ignore quality specifications in accept-encoding + // ex. gzip;q=0.8 + if (!str.contains(';')) return str; + return str.split(';')[0]; + }); + } + + bool _openStream() { + if (!_streamInitialized) { + // If this is the first stream added to this response, + // then add headers, status code, etc. + var outHeaders = {}; + var statusLine = + utf8.encode('HTTP/1.1 $statusCode').followedBy([$cr, $lf]); + writeToNativeSocket(rawResponse, Uint8List.fromList(statusLine.toList())); + + headers.forEach((k, v) => outHeaders[k] = v); + + if (headers.containsKey('content-length')) { + var l = int.tryParse(headers['content-length']); + if (l != null) { + outHeaders['content-length'] = l.toString(); + } + } + + if (contentType != null) { + outHeaders['content-type'] = contentType.toString(); + } + + if (encoders.isNotEmpty && correspondingRequest != null) { + if (_allowedEncodings != null) { + for (var encodingName in _allowedEncodings) { + Converter, List> encoder; + String key = encodingName; + + if (encoders.containsKey(encodingName)) { + encoder = encoders[encodingName]; + } else if (encodingName == '*') { + encoder = encoders[key = encoders.keys.first]; + } + + if (encoder != null) { + outHeaders['content-encoding'] = key; + break; + } + } + } + } + + void _wh(String k, String v) { + // var vv =Uri.encodeComponent(v); + var vv = v; + var headerLine = utf8.encode('$k: $vv').followedBy([$cr, $lf]); + writeToNativeSocket( + rawResponse, Uint8List.fromList(headerLine.toList())); + } + + outHeaders.forEach(_wh); + + for (var c in cookies) { + _wh('set-cookie', c.toString()); + } + + writeToNativeSocket(rawResponse, Uint8List.fromList([$cr, $lf])); + + //_isClosed = true; + return _streamInitialized = true; + } + + return false; + } + + @override + Future addStream(Stream> stream) { + if (_isClosed && isBuffered) throw ResponseContext.closed(); + _openStream(); + + Stream> output = stream; + + if (encoders.isNotEmpty && correspondingRequest != null) { + if (_allowedEncodings != null) { + for (var encodingName in _allowedEncodings) { + Converter, List> encoder; + String key = encodingName; + + if (encoders.containsKey(encodingName)) { + encoder = encoders[encodingName]; + } else if (encodingName == '*') { + encoder = encoders[key = encoders.keys.first]; + } + + if (encoder != null) { + output = encoders[key].bind(output); + break; + } + } + } + } + + return output.forEach((buf) { + if (!_isClosed) { + writeToNativeSocket( + rawResponse, buf is Uint8List ? buf : Uint8List.fromList(buf)); + } + }); + } + + @override + void add(List data) { + if (_isClosed && isBuffered) { + throw ResponseContext.closed(); + } else if (!isBuffered) { + if (!_isClosed) { + _openStream(); + + if (encoders.isNotEmpty && correspondingRequest != null) { + if (_allowedEncodings != null) { + for (var encodingName in _allowedEncodings) { + Converter, List> encoder; + String key = encodingName; + + if (encoders.containsKey(encodingName)) { + encoder = encoders[encodingName]; + } else if (encodingName == '*') { + encoder = encoders[key = encoders.keys.first]; + } + + if (encoder != null) { + data = encoders[key].convert(data); + break; + } + } + } + } + + writeToNativeSocket( + rawResponse, data is Uint8List ? data : Uint8List.fromList(data)); + } + } else { + buffer.add(data); + } + } + + @override + Future close() async { + if (!_isDetached) { + if (!_isClosed) { + _isClosed = true; + if (!isBuffered) { + _openStream(); + closeNativeSocketDescriptor(rawResponse); + } else { + _buffer.lock(); + } + } + + await correspondingRequest?.close(); + await super.close(); + } + } + + @override + BytesBuilder get buffer => _buffer; + + @override + int detach() { + _isDetached = true; + return rawResponse; + } + + @override + bool get isBuffered => _buffer != null; + + @override + bool get isOpen => !_isClosed && !_isDetached; + + @override + void useBuffer() { + _buffer = LockableBytesBuilder(); + } +} diff --git a/packages/wings/lib/src/wings_socket.cc b/packages/wings/lib/src/wings_socket.cc new file mode 100644 index 00000000..7105b2ee --- /dev/null +++ b/packages/wings/lib/src/wings_socket.cc @@ -0,0 +1,129 @@ +#include "wings_socket.h" +#include +#include +#include +using namespace wings; + +std::vector wings::globalSocketList; + +bool WingsSocketInfo::equals(const WingsSocketInfo &right) const { + // std::cout << address << " vs " << right.address << std::endl; + // std::cout << port << " vs " << right.port << std::endl; + return (strcmp(address, right.address) == 0) && port == right.port; +} + +WingsSocket::WingsSocket(sa_family_t family, int sockfd, + const WingsSocketInfo &info) + : sockfd(sockfd), info(info), family(family) { + portIterator = sendPorts.begin(); + open = true; + refCount = 0; + workerThread = nullptr; + this->info.address = strdup(info.address); +} + +void WingsSocket::incrRef(Dart_Port port) { + refCount++; + sendPorts.push_back(port); +} + +void WingsSocket::decrRef(Dart_Port port) { + auto it = std::find(sendPorts.begin(), sendPorts.end(), port); + + if (it != sendPorts.end()) { + sendPorts.erase(it); + } + + refCount--; + + if (refCount <= 0 && open) { + close(sockfd); + open = false; + } +} + +Dart_Port WingsSocket::nextPort() { + portIterator++; + if (portIterator == sendPorts.end()) + portIterator = sendPorts.begin(); + return *portIterator; +} + +const WingsSocketInfo &WingsSocket::getInfo() const { return info; } + +int WingsSocket::getFD() const { return sockfd; } + +sa_family_t WingsSocket::getFamily() const { return family; } + +bool WingsSocket::isClosed() const { return !open; } + +void WingsSocket::start(Dart_NativeArguments arguments) { + // if (workerThread == nullptr) + // { + // workerThread = std::make_unique(threadCallback, this); + // } + Dart_Port service_port = + Dart_NewNativePort("WingsThreadCallback", &threadCallback, true); + Dart_Handle send_port = Dart_NewSendPort(service_port); + Dart_SetReturnValue(arguments, send_port); +} + +void WingsSocket::threadCallback(Dart_Port dest_port_id, + Dart_CObject *message) { + + WingsSocket *socket = nullptr; + Dart_Port outPort = message->value.as_array.values[0]->value.as_send_port.id; + Dart_CObject *ptrArg = message->value.as_array.values[1]; + + // If there are no listeners, quit. + if (ptrArg->type == Dart_CObject_kInt32) { + auto as64 = (int64_t)ptrArg->value.as_int32; + socket = (WingsSocket *)as64; + } else { + socket = (WingsSocket *)ptrArg->value.as_int64; + } + + if (socket != nullptr) { + if (socket->sendPorts.empty() || socket->isClosed()) { + return; + } + + int sock; + unsigned long index = 0; + sockaddr addr; + socklen_t len; + + if ((sock = accept(socket->sockfd, &addr, &len)) != -1) { + char addrBuf[INET6_ADDRSTRLEN] = {0}; + + if (addr.sa_family == AF_INET6) { + auto as6 = (sockaddr_in6 *)&addr; + inet_ntop(addr.sa_family, &(as6->sin6_addr), addrBuf, len); + } else { + auto as4 = (sockaddr_in *)&addr; + inet_ntop(AF_INET, &(as4->sin_addr), addrBuf, len); + } + + Dart_CObject fdObj; + fdObj.type = Dart_CObject_kInt64; + fdObj.value.as_int64 = sock; + + Dart_CObject addrObj; + addrObj.type = Dart_CObject_kString; + addrObj.value.as_string = addrBuf; + + Dart_CObject *values[2] = {&fdObj, &addrObj}; + + Dart_CObject obj; + obj.type = Dart_CObject_kArray; + obj.value.as_array.length = 2; + obj.value.as_array.values = values; + + // Dart_PostCObject(outPort, &obj); + // Dispatch the fd to the next listener. + auto port = socket->nextPort(); + Dart_PostCObject(port, &obj); + // Dart_PostCObject(outPort, &obj); + } + } +} \ No newline at end of file diff --git a/packages/wings/lib/src/wings_socket.dart b/packages/wings/lib/src/wings_socket.dart new file mode 100644 index 00000000..f2222e2a --- /dev/null +++ b/packages/wings/lib/src/wings_socket.dart @@ -0,0 +1,130 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:isolate'; +import 'dart:typed_data'; +import 'dart-ext:angel_wings'; + +int bindWingsIPv4ServerSocket( + String address, + int port, + bool shared, + int backlog, + bool v6Only, + SendPort sendPort) native 'Dart_WingsSocket_bindIPv4'; + +int bindWingsIPv6ServerSocket( + String address, + int port, + bool shared, + int backlog, + bool v6Only, + SendPort sendPort) native 'Dart_WingsSocket_bindIPv6'; + +String getWingsServerSocketAddress(int pointer) + native 'Dart_WingsSocket_getAddress'; + +int getWingsServerSocketPort(int pointer) native 'Dart_WingsSocket_getPort'; + +void writeToNativeSocket(int fd, Uint8List data) + native 'Dart_WingsSocket_write'; + +void closeNativeSocketDescriptor(int fd) + native 'Dart_WingsSocket_closeDescriptor'; + +SendPort wingsSocketListen(int pointer) native 'Dart_WingsSocket_listen'; + +void closeWingsSocket(int pointer, SendPort sendPort) + native 'Dart_WingsSocket_close'; + +SendPort wingsParseHttp() native 'Dart_WingsSocket_parseHttp'; + +class WingsClientSocket { + final int fileDescriptor; + final InternetAddress remoteAddress; + + WingsClientSocket(this.fileDescriptor, this.remoteAddress); +} + +class WingsSocket extends Stream { + final StreamController _ctrl = StreamController(); + SendPort _acceptor; + InternetAddress _address; + final int _pointer; + final RawReceivePort _recv; + bool _open = true; + int _port; + + WingsSocket._(this._pointer, this._recv) { + _acceptor = wingsSocketListen(_pointer); + _recv.handler = (h) { + if (!_ctrl.isClosed) { + _ctrl.add( + WingsClientSocket(h[0] as int, InternetAddress(h[1] as String))); + _acceptor.send([_recv.sendPort, _pointer]); + } + }; + + _acceptor.send([_recv.sendPort, _pointer]); + } + + static Future bind(address, int port, + {bool shared = false, int backlog = 0, bool v6Only = false}) async { + var recv = RawReceivePort(); + int ptr; + InternetAddress addr; + + if (address is InternetAddress) { + addr = address; + } else if (address is String) { + var addrs = await InternetAddress.lookup(address); + if (addrs.isNotEmpty) { + addr = addrs[0]; + } else { + throw StateError('Internet address lookup failed: $address'); + } + } else { + throw ArgumentError.value( + address, 'address', 'must be an InternetAddress or String'); + } + + try { + if (addr.type == InternetAddressType.IPv6) { + ptr = bindWingsIPv6ServerSocket( + addr.address, port, shared, backlog, v6Only, recv.sendPort); + } else { + ptr = bindWingsIPv4ServerSocket( + addr.address, port, shared, backlog, v6Only, recv.sendPort); + } + + return WingsSocket._(ptr, recv); //.._address = addr; + } catch (e) { + recv.close(); + rethrow; + } + } + + InternetAddress get address => + _address ??= InternetAddress(getWingsServerSocketAddress(_pointer)); + + int get port => _port ??= getWingsServerSocketPort(_pointer); + + @override + StreamSubscription listen( + void Function(WingsClientSocket event) onData, + {Function onError, + void Function() onDone, + bool cancelOnError}) { + return _ctrl.stream + .listen(onData, onError: onError, cancelOnError: cancelOnError); + } + + Future close(){ + if (_open) { + _open = false; + closeWingsSocket(_pointer, _recv.sendPort); + _recv.close(); + _ctrl.close(); + } + return Future.value(); + } +} diff --git a/packages/wings/lib/src/wings_socket.h b/packages/wings/lib/src/wings_socket.h new file mode 100644 index 00000000..37336917 --- /dev/null +++ b/packages/wings/lib/src/wings_socket.h @@ -0,0 +1,54 @@ +#ifndef WINGS_SOCKET_H +#define WINGS_SOCKET_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace wings { +struct WingsSocketInfo { + const char *address; + uint64_t port; + bool shared; + uint64_t backlog; + bool v6Only; + Dart_Handle sendPortHandle; + bool equals(const WingsSocketInfo &right) const; +}; + +class WingsSocket { +public: + WingsSocket(sa_family_t family, int sockfd, const WingsSocketInfo &info); + void incrRef(Dart_Port port); + void decrRef(Dart_Port port); + const WingsSocketInfo &getInfo() const; + void start(Dart_NativeArguments arguments); + int getFD() const; + bool isClosed() const; + sa_family_t getFamily() const; + Dart_Port nextPort(); + +private: + static void threadCallback(Dart_Port dest_port_id, Dart_CObject *message); + WingsSocketInfo info; + std::list::iterator portIterator; + int sockfd; + int refCount; + bool open; + sa_family_t family; + std::unique_ptr workerThread; + std::list sendPorts; +}; + +extern std::vector globalSocketList; +} // namespace wings + +#endif \ No newline at end of file diff --git a/packages/wings/libangel_wings.dylib b/packages/wings/libangel_wings.dylib new file mode 100755 index 00000000..fbcfc381 Binary files /dev/null and b/packages/wings/libangel_wings.dylib differ diff --git a/packages/wings/libangel_wings.so b/packages/wings/libangel_wings.so new file mode 100644 index 00000000..92b8f107 Binary files /dev/null and b/packages/wings/libangel_wings.so differ diff --git a/packages/wings/provision.sh b/packages/wings/provision.sh new file mode 100755 index 00000000..345eb439 --- /dev/null +++ b/packages/wings/provision.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash + +# Install Dart, globally. +sudo apt-get update +sudo apt-get install apt-transport-https +sudo sh -c 'curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -' +sudo sh -c 'curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list' +sudo apt-get update +sudo apt-get install -y dart +export PATH="$PATH:/usr/lib/dart/bin" +echo 'export PATH="$PATH:/usr/lib/dart/bin"' >> ~vagrant/.profile + +# Install build tooling, CMake, etc. +sudo apt-get install -y build-essential +sudo apt-get install -y cmake + +# Build the library. +pushd /vagrant +mkdir -p cmake-build-vagrant +pushd cmake-build-vagrant +cmake .. +cmake --build . --target install +popd +popd diff --git a/packages/wings/pubspec.yaml b/packages/wings/pubspec.yaml new file mode 100644 index 00000000..c04e9505 --- /dev/null +++ b/packages/wings/pubspec.yaml @@ -0,0 +1,11 @@ +name: angel_wings +environment: + sdk: ">=2.0.0-dev <3.0.0" +dependencies: + angel_framework: ^2.0.0-alpha + mock_request: ^1.0.0 +dev_dependencies: + angel_static: ^2.0.0 + io: ^0.3.2 + pedantic: ^1.0.0 + pretty_logging: ^1.0.0 \ No newline at end of file diff --git a/packages/wings/ubuntu-bionic-18.04-cloudimg-console.log b/packages/wings/ubuntu-bionic-18.04-cloudimg-console.log new file mode 100644 index 00000000..63e6554b --- /dev/null +++ b/packages/wings/ubuntu-bionic-18.04-cloudimg-console.log @@ -0,0 +1,672 @@ +[ 0.000000] Linux version 4.15.0-60-generic (buildd@lgw01-amd64-030) (gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)) #67-Ubuntu SMP Thu Aug 22 16:55:30 UTC 2019 (Ubuntu 4.15.0-60.67-generic 4.15.18) +[ 0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-4.15.0-60-generic root=LABEL=cloudimg-rootfs ro console=tty1 console=ttyS0 +[ 0.000000] KERNEL supported cpus: +[ 0.000000] Intel GenuineIntel +[ 0.000000] AMD AuthenticAMD +[ 0.000000] Centaur CentaurHauls +[ 0.000000] x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers' +[ 0.000000] x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers' +[ 0.000000] x86/fpu: Supporting XSAVE feature 0x004: 'AVX registers' +[ 0.000000] x86/fpu: xstate_offset[2]: 576, xstate_sizes[2]: 256 +[ 0.000000] x86/fpu: Enabled xstate features 0x7, context size is 832 bytes, using 'standard' format. +[ 0.000000] e820: BIOS-provided physical RAM map: +[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable +[ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved +[ 0.000000] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved +[ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000003ffeffff] usable +[ 0.000000] BIOS-e820: [mem 0x000000003fff0000-0x000000003fffffff] ACPI data +[ 0.000000] BIOS-e820: [mem 0x00000000fec00000-0x00000000fec00fff] reserved +[ 0.000000] BIOS-e820: [mem 0x00000000fee00000-0x00000000fee00fff] reserved +[ 0.000000] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved +[ 0.000000] NX (Execute Disable) protection: active +[ 0.000000] SMBIOS 2.5 present. +[ 0.000000] DMI: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 +[ 0.000000] Hypervisor detected: KVM +[ 0.000000] e820: last_pfn = 0x3fff0 max_arch_pfn = 0x400000000 +[ 0.000000] MTRR: Disabled +[ 0.000000] x86/PAT: MTRRs disabled, skipping PAT initialization too. +[ 0.000000] CPU MTRRs all blank - virtualized system. +[ 0.000000] x86/PAT: Configuration [0-7]: WB WT UC- UC WB WT UC- UC +[ 0.000000] found SMP MP-table at [mem 0x0009fff0-0x0009ffff] +[ 0.000000] Scanning 1 areas for low memory corruption +[ 0.000000] RAMDISK: [mem 0x35a8b000-0x36d3cfff] +[ 0.000000] ACPI: Early table checksum verification disabled +[ 0.000000] ACPI: RSDP 0x00000000000E0000 000024 (v02 VBOX ) +[ 0.000000] ACPI: XSDT 0x000000003FFF0030 00003C (v01 VBOX VBOXXSDT 00000001 ASL 00000061) +[ 0.000000] ACPI: FACP 0x000000003FFF00F0 0000F4 (v04 VBOX VBOXFACP 00000001 ASL 00000061) +[ 0.000000] ACPI: DSDT 0x000000003FFF0470 0022EA (v02 VBOX VBOXBIOS 00000002 INTL 20100528) +[ 0.000000] ACPI: FACS 0x000000003FFF0200 000040 +[ 0.000000] ACPI: FACS 0x000000003FFF0200 000040 +[ 0.000000] ACPI: APIC 0x000000003FFF0240 00005C (v02 VBOX VBOXAPIC 00000001 ASL 00000061) +[ 0.000000] ACPI: SSDT 0x000000003FFF02A0 0001CC (v01 VBOX VBOXCPUT 00000002 INTL 20100528) +[ 0.000000] No NUMA configuration found +[ 0.000000] Faking a node at [mem 0x0000000000000000-0x000000003ffeffff] +[ 0.000000] NODE_DATA(0) allocated [mem 0x3ffc5000-0x3ffeffff] +[ 0.000000] kvm-clock: cpu 0, msr 0:3ff44001, primary cpu clock +[ 0.000000] kvm-clock: Using msrs 4b564d01 and 4b564d00 +[ 0.000000] kvm-clock: using sched offset of 6313796290 cycles +[ 0.000000] clocksource: kvm-clock: mask: 0xffffffffffffffff max_cycles: 0x1cd42e4dffb, max_idle_ns: 881590591483 ns +[ 0.000000] Zone ranges: +[ 0.000000] DMA [mem 0x0000000000001000-0x0000000000ffffff] +[ 0.000000] DMA32 [mem 0x0000000001000000-0x000000003ffeffff] +[ 0.000000] Normal empty +[ 0.000000] Device empty +[ 0.000000] Movable zone start for each node +[ 0.000000] Early memory node ranges +[ 0.000000] node 0: [mem 0x0000000000001000-0x000000000009efff] +[ 0.000000] node 0: [mem 0x0000000000100000-0x000000003ffeffff] +[ 0.000000] Reserved but unavailable: 98 pages +[ 0.000000] Initmem setup node 0 [mem 0x0000000000001000-0x000000003ffeffff] +[ 0.000000] ACPI: PM-Timer IO Port: 0x4008 +[ 0.000000] IOAPIC[0]: apic_id 2, version 32, address 0xfec00000, GSI 0-23 +[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 0 global_irq 2 dfl dfl) +[ 0.000000] ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level) +[ 0.000000] Using ACPI (MADT) for SMP configuration information +[ 0.000000] smpboot: Allowing 2 CPUs, 0 hotplug CPUs +[ 0.000000] PM: Registered nosave memory: [mem 0x00000000-0x00000fff] +[ 0.000000] PM: Registered nosave memory: [mem 0x0009f000-0x0009ffff] +[ 0.000000] PM: Registered nosave memory: [mem 0x000a0000-0x000effff] +[ 0.000000] PM: Registered nosave memory: [mem 0x000f0000-0x000fffff] +[ 0.000000] e820: [mem 0x40000000-0xfebfffff] available for PCI devices +[ 0.000000] Booting paravirtualized kernel on KVM +[ 0.000000] clocksource: refined-jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645519600211568 ns +[ 0.000000] random: get_random_bytes called from start_kernel+0x99/0x4fd with crng_init=0 +[ 0.000000] setup_percpu: NR_CPUS:8192 nr_cpumask_bits:2 nr_cpu_ids:2 nr_node_ids:1 +[ 0.000000] percpu: Embedded 46 pages/cpu s151552 r8192 d28672 u1048576 +[ 0.000000] PV qspinlock hash table entries: 256 (order: 0, 4096 bytes) +[ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 257913 +[ 0.000000] Policy zone: DMA32 +[ 0.000000] Kernel command line: BOOT_IMAGE=/boot/vmlinuz-4.15.0-60-generic root=LABEL=cloudimg-rootfs ro console=tty1 console=ttyS0 +[ 0.000000] Memory: 983440K/1048120K available (12300K kernel code, 2481K rwdata, 4172K rodata, 2436K init, 2384K bss, 64680K reserved, 0K cma-reserved) +[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=2, Nodes=1 +[ 0.000000] Kernel/User page tables isolation: enabled +[ 0.000000] ftrace: allocating 39306 entries in 154 pages +[ 0.004000] Hierarchical RCU implementation. +[ 0.004000] RCU restricting CPUs from NR_CPUS=8192 to nr_cpu_ids=2. +[ 0.004000] Tasks RCU enabled. +[ 0.004000] RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2 +[ 0.004000] NR_IRQS: 524544, nr_irqs: 440, preallocated irqs: 16 +[ 0.004000] Console: colour VGA+ 80x25 +[ 0.004000] console [tty1] enabled +[ 0.004000] console [ttyS0] enabled +[ 0.004000] ACPI: Core revision 20170831 +[ 0.004000] ACPI: 2 ACPI AML tables successfully acquired and loaded +[ 0.004000] APIC: Switch to symmetric I/O mode setup +[ 0.004000] x2apic enabled +[ 0.004000] Switched APIC routing to physical x2apic. +[ 0.005261] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1 +[ 0.008004] tsc: Detected 1799.999 MHz processor +[ 0.012012] Calibrating delay loop (skipped) preset value.. 3599.99 BogoMIPS (lpj=7199996) +[ 0.014430] pid_max: default: 32768 minimum: 301 +[ 0.016036] Security Framework initialized +[ 0.017257] Yama: becoming mindful. +[ 0.018593] AppArmor: AppArmor initialized +[ 0.021844] Dentry cache hash table entries: 131072 (order: 8, 1048576 bytes) +[ 0.024088] Inode-cache hash table entries: 65536 (order: 7, 524288 bytes) +[ 0.028022] Mount-cache hash table entries: 2048 (order: 2, 16384 bytes) +[ 0.030085] Mountpoint-cache hash table entries: 2048 (order: 2, 16384 bytes) +[ 0.032346] Last level iTLB entries: 4KB 64, 2MB 8, 4MB 8 +[ 0.036002] Last level dTLB entries: 4KB 64, 2MB 0, 4MB 0, 1GB 4 +[ 0.038331] Spectre V1 : Mitigation: usercopy/swapgs barriers and __user pointer sanitization +[ 0.040053] Spectre V2 : Mitigation: Full generic retpoline +[ 0.044003] Spectre V2 : Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch +[ 0.047370] Speculative Store Bypass: Vulnerable +[ 0.048050] MDS: Vulnerable: Clear CPU buffers attempted, no microcode +[ 0.050738] Freeing SMP alternatives memory: 36K +[ 0.060000] smpboot: CPU0: Intel(R) Core(TM) i5-5350U CPU @ 1.80GHz (family: 0x6, model: 0x3d, stepping: 0x4) +[ 0.060095] Performance Events: unsupported p6 CPU model 61 no PMU driver, software events only. +[ 0.063096] Hierarchical SRCU implementation. +[ 0.064650] NMI watchdog: Perf event create on CPU 0 failed with -2 +[ 0.066472] NMI watchdog: Perf NMI watchdog permanently disabled +[ 0.068053] smp: Bringing up secondary CPUs ... +[ 0.069490] x86: Booting SMP configuration: +[ 0.070770] .... node #0, CPUs: #1 +[ 0.004000] kvm-clock: cpu 1, msr 0:3ff44041, secondary cpu clock +[ 0.078095] smp: Brought up 1 node, 2 CPUs +[ 0.078095] smpboot: Max logical packages: 1 +[ 0.080007] smpboot: Total of 2 processors activated (7199.99 BogoMIPS) +[ 0.085029] devtmpfs: initialized +[ 0.085718] x86/mm: Memory block size: 128MB +[ 0.088152] evm: security.selinux +[ 0.089578] evm: security.SMACK64 +[ 0.090723] evm: security.SMACK64EXEC +[ 0.092005] evm: security.SMACK64TRANSMUTE +[ 0.093324] evm: security.SMACK64MMAP +[ 0.094789] evm: security.apparmor +[ 0.096003] evm: security.ima +[ 0.097270] evm: security.capability +[ 0.100127] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns +[ 0.104010] futex hash table entries: 512 (order: 3, 32768 bytes) +[ 0.108000] pinctrl core: initialized pinctrl subsystem +[ 0.108153] RTC time: 4:37:25, date: 09/29/19 +[ 0.112223] NET: Registered protocol family 16 +[ 0.114097] audit: initializing netlink subsys (disabled) +[ 0.116040] audit: type=2000 audit(1569731852.938:1): state=initialized audit_enabled=0 res=1 +[ 0.120020] cpuidle: using governor ladder +[ 0.121972] cpuidle: using governor menu +[ 0.124054] ACPI: bus type PCI registered +[ 0.125660] acpiphp: ACPI Hot Plug PCI Controller Driver version: 0.5 +[ 0.128144] PCI: Using configuration type 1 for base access +[ 0.132420] HugeTLB registered 2.00 MiB page size, pre-allocated 0 pages +[ 0.136070] ACPI: Added _OSI(Module Device) +[ 0.137755] ACPI: Added _OSI(Processor Device) +[ 0.139558] ACPI: Added _OSI(3.0 _SCP Extensions) +[ 0.140012] ACPI: Added _OSI(Processor Aggregator Device) +[ 0.142205] ACPI: Added _OSI(Linux-Dell-Video) +[ 0.144009] ACPI: Added _OSI(Linux-Lenovo-NV-HDMI-Audio) +[ 0.146265] ACPI: Added _OSI(Linux-HPI-Hybrid-Graphics) +[ 0.148559] ACPI: Executed 1 blocks of module-level executable AML code +[ 0.157460] ACPI: Interpreter enabled +[ 0.159031] ACPI: (supports S0 S5) +[ 0.160004] ACPI: Using IOAPIC for interrupt routing +[ 0.162232] PCI: Using host bridge windows from ACPI; if necessary, use "pci=nocrs" and report a bug +[ 0.164282] ACPI: Enabled 2 GPEs in block 00 to 07 +[ 0.177420] ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff]) +[ 0.179619] acpi PNP0A03:00: _OSC: OS supports [ASPM ClockPM Segments MSI] +[ 0.180559] acpi PNP0A03:00: _OSC: not requesting OS control; OS requires [ExtendedConfig ASPM ClockPM MSI] +[ 0.184016] acpi PNP0A03:00: fail to add MMCONFIG information, can't access extended PCI configuration space under this bridge. +[ 0.188599] PCI host bridge to bus 0000:00 +[ 0.190032] pci_bus 0000:00: root bus resource [io 0x0000-0x0cf7 window] +[ 0.192012] pci_bus 0000:00: root bus resource [io 0x0d00-0xffff window] +[ 0.196010] pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff window] +[ 0.198997] pci_bus 0000:00: root bus resource [mem 0x40000000-0xfdffffff window] +[ 0.200005] pci_bus 0000:00: root bus resource [bus 00-ff] +[ 0.209096] pci 0000:00:01.1: legacy IDE quirk: reg 0x10: [io 0x01f0-0x01f7] +[ 0.212011] pci 0000:00:01.1: legacy IDE quirk: reg 0x14: [io 0x03f6] +[ 0.214198] pci 0000:00:01.1: legacy IDE quirk: reg 0x18: [io 0x0170-0x0177] +[ 0.216011] pci 0000:00:01.1: legacy IDE quirk: reg 0x1c: [io 0x0376] +[ 0.250063] pci 0000:00:07.0: quirk: [io 0x4000-0x403f] claimed by PIIX4 ACPI +[ 0.252032] pci 0000:00:07.0: quirk: [io 0x4100-0x410f] claimed by PIIX4 SMB +[ 0.268428] ACPI: PCI Interrupt Link [LNKA] (IRQs 5 9 10 *11) +[ 0.271342] ACPI: PCI Interrupt Link [LNKB] (IRQs 5 9 *10 11) +[ 0.272177] ACPI: PCI Interrupt Link [LNKC] (IRQs 5 *9 10 11) +[ 0.274371] ACPI: PCI Interrupt Link [LNKD] (IRQs 5 9 10 *11) +[ 0.276529] SCSI subsystem initialized +[ 0.280075] pci 0000:00:02.0: vgaarb: setting as boot VGA device +[ 0.282678] pci 0000:00:02.0: vgaarb: VGA device added: decodes=io+mem,owns=io+mem,locks=none +[ 0.284008] pci 0000:00:02.0: vgaarb: bridge control possible +[ 0.288007] vgaarb: loaded +[ 0.289501] ACPI: bus type USB registered +[ 0.292045] usbcore: registered new interface driver usbfs +[ 0.294316] usbcore: registered new interface driver hub +[ 0.296044] usbcore: registered new device driver usb +[ 0.300127] EDAC MC: Ver: 3.0.0 +[ 0.302311] PCI: Using ACPI for IRQ routing +[ 0.304830] NetLabel: Initializing +[ 0.308006] NetLabel: domain hash size = 128 +[ 0.310637] NetLabel: protocols = UNLABELED CIPSOv4 CALIPSO +[ 0.312043] NetLabel: unlabeled traffic allowed by default +[ 0.316129] clocksource: Switched to clocksource kvm-clock +[ 0.338523] VFS: Disk quotas dquot_6.6.0 +[ 0.340526] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes) +[ 0.344063] AppArmor: AppArmor Filesystem Enabled +[ 0.347415] pnp: PnP ACPI init +[ 0.354536] pnp: PnP ACPI: found 3 devices +[ 0.377986] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns +[ 0.384610] NET: Registered protocol family 2 +[ 0.391662] TCP established hash table entries: 8192 (order: 4, 65536 bytes) +[ 0.396743] TCP bind hash table entries: 8192 (order: 5, 131072 bytes) +[ 0.401916] TCP: Hash tables configured (established 8192 bind 8192) +[ 0.406238] UDP hash table entries: 512 (order: 2, 16384 bytes) +[ 0.409854] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes) +[ 0.414792] NET: Registered protocol family 1 +[ 0.418002] pci 0000:00:00.0: Limiting direct PCI/PCI transfers +[ 0.423100] pci 0000:00:01.0: Activating ISA DMA hang workarounds +[ 0.427601] pci 0000:00:02.0: Video device with shadowed ROM at [mem 0x000c0000-0x000dffff] +[ 0.434649] Unpacking initramfs... +[ 0.787407] Freeing initrd memory: 19144K +[ 0.789209] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x19f228ab7a2, max_idle_ns: 440795289252 ns +[ 0.793332] platform rtc_cmos: registered platform RTC device (no PNP device found) +[ 0.796800] Scanning for low memory corruption every 60 seconds +[ 0.799238] Initialise system trusted keyrings +[ 0.801081] Key type blacklist registered +[ 0.802821] workingset: timestamp_bits=36 max_order=18 bucket_order=0 +[ 0.805819] zbud: loaded +[ 0.807186] squashfs: version 4.0 (2009/01/31) Phillip Lougher +[ 0.810037] fuse init (API version 7.26) +[ 0.815469] Key type asymmetric registered +[ 0.816858] Asymmetric key parser 'x509' registered +[ 0.818479] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 246) +[ 0.821254] io scheduler noop registered +[ 0.822470] io scheduler deadline registered +[ 0.823827] io scheduler cfq registered (default) +[ 0.826132] ACPI: AC Adapter [AC] (on-line) +[ 0.827462] input: Power Button as /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0 +[ 0.830032] ACPI: Power Button [PWRF] +[ 0.831785] input: Sleep Button as /devices/LNXSYSTM:00/LNXSLPBN:00/input/input1 +[ 0.834809] ACPI: Sleep Button [SLPF] +[ 0.838210] ACPI: Battery Slot [BAT0] (battery present) +[ 0.840233] Serial: 8250/16550 driver, 32 ports, IRQ sharing enabled + +  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~[ 0.869459] 00:02: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A +[ 0.873870] Linux agpgart interface v0.103 +[ 0.876700] loop: module loaded +[ 0.878775] scsi host0: ata_piix +[ 0.880366] scsi host1: ata_piix +[ 0.881737] ata1: PATA max UDMA/33 cmd 0x1f0 ctl 0x3f6 bmdma 0xd000 irq 14 +[ 0.883885] ata2: PATA max UDMA/33 cmd 0x170 ctl 0x376 bmdma 0xd008 irq 15 +[ 0.886091] libphy: Fixed MDIO Bus: probed +[ 0.887767] tun: Universal TUN/TAP device driver, 1.6 +[ 0.889455] PPP generic driver version 2.4.2 +[ 0.890748] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver +[ 0.892752] ehci-pci: EHCI PCI platform driver +[ 0.894121] ehci-platform: EHCI generic platform driver +[ 0.895894] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver +[ 0.898361] ohci-pci: OHCI PCI platform driver +[ 0.900140] ohci-platform: OHCI generic platform driver +[ 0.902441] uhci_hcd: USB Universal Host Controller Interface driver +[ 0.904865] i8042: PNP: PS/2 Controller [PNP0303:PS2K,PNP0f03:PS2M] at 0x60,0x64 irq 1,12 +[ 0.907797] serio: i8042 KBD port at 0x60,0x64 irq 1 +[ 0.909401] serio: i8042 AUX port at 0x60,0x64 irq 12 +[ 0.910962] mousedev: PS/2 mouse device common for all mice +[ 0.913441] input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input2 +[ 0.916486] rtc_cmos rtc_cmos: rtc core: registered rtc_cmos as rtc0 +[ 0.918365] rtc_cmos rtc_cmos: alarms up to one day, 114 bytes nvram +[ 0.920021] i2c /dev entries driver +[ 0.921365] device-mapper: uevent: version 1.0.3 +[ 0.922803] device-mapper: ioctl: 4.37.0-ioctl (2017-09-20) initialised: dm-devel@redhat.com +[ 0.926126] ledtrig-cpu: registered to indicate activity on CPUs +[ 0.929176] NET: Registered protocol family 10 +[ 0.937552] Segment Routing with IPv6 +[ 0.938709] NET: Registered protocol family 17 +[ 0.940188] Key type dns_resolver registered +[ 0.941836] mce: Using 0 MCE banks +[ 0.943170] RAS: Correctable Errors collector initialized. +[ 0.945569] sched_clock: Marking stable (945543331, 0)->(1319832110, -374288779) +[ 0.948649] registered taskstats version 1 +[ 0.949901] Loading compiled-in X.509 certificates +[ 0.954626] Loaded X.509 cert 'Build time autogenerated kernel key: 9d88e3c0462fa0d2df2917e8bbfdfdd1c55d8ddc' +[ 0.958110] zswap: loaded using pool lzo/zbud +[ 0.964498] Key type big_key registered +[ 0.965808] Key type trusted registered +[ 0.969372] Key type encrypted registered +[ 0.970893] AppArmor: AppArmor sha1 policy hashing enabled +[ 0.973159] ima: No TPM chip found, activating TPM-bypass! (rc=-19) +[ 0.975617] ima: Allocated hash algorithm: sha1 +[ 0.977534] evm: HMAC attrs: 0x1 +[ 0.979719] Magic number: 3:202:617 +[ 0.982579] rtc_cmos rtc_cmos: setting system clock to 2019-09-29 04:37:26 UTC (1569731846) +[ 0.986467] BIOS EDD facility v0.16 2004-Jun-25, 0 devices found +[ 0.988892] EDD information not available. +[ 1.049273] Freeing unused kernel image memory: 2436K +[ 1.064568] Write protecting the kernel read-only data: 20480k +[ 1.067065] Freeing unused kernel image memory: 2008K +[ 1.069111] Freeing unused kernel image memory: 1972K +[ 1.077828] x86/mm: Checked W+X mappings: passed, no W+X pages found. +[ 1.080111] x86/mm: Checking user space page tables +[ 1.089009] x86/mm: Checked W+X mappings: passed, no W+X pages found. +Loading, please wait... +starting version 237 +[ 1.184353] Fusion MPT base driver 3.04.20 +[ 1.186024] Copyright (c) 1999-2008 LSI Corporation +[ 1.196999] e1000: Intel(R) PRO/1000 Network Driver - version 7.3.21-k8-NAPI +[ 1.199908] e1000: Copyright (c) 1999-2006 Intel Corporation. +[ 1.208654] Fusion MPT SPI Host driver 3.04.20 +[ 1.224491] AVX2 version of gcm_enc/dec engaged. +[ 1.231798] AES CTR mode by8 optimization enabled +[ 1.419237] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input4 +[ 1.843515] e1000 0000:00:03.0 eth0: (PCI:33MHz:32-bit) 02:ee:0a:3b:45:98 +[ 1.846823] e1000 0000:00:03.0 eth0: Intel(R) PRO/1000 Network Connection +[ 1.851174] mptbase: ioc0: Initiating bringup +[ 1.851551] e1000 0000:00:03.0 enp0s3: renamed from eth0 +[ 1.952561] ioc0: LSI53C1030 A0: Capabilities={Initiator} +[ 2.195418] scsi host2: ioc0: LSI53C1030 A0, FwRev=00000000h, Ports=1, MaxQ=256, IRQ=20 +[ 2.365548] scsi 2:0:0:0: Direct-Access VBOX HARDDISK 1.0 PQ: 0 ANSI: 5 +[ 2.400288] scsi target2:0:0: Beginning Domain Validation +[ 2.405262] scsi target2:0:0: Domain Validation skipping write tests +[ 2.407797] scsi target2:0:0: Ending Domain Validation +[ 2.410045] scsi target2:0:0: asynchronous +[ 2.413130] scsi 2:0:1:0: Direct-Access VBOX HARDDISK 1.0 PQ: 0 ANSI: 5 +[ 2.444548] scsi target2:0:1: Beginning Domain Validation +[ 2.447997] random: fast init done +[ 2.450934] scsi target2:0:1: Domain Validation skipping write tests +[ 2.453478] scsi target2:0:1: Ending Domain Validation +[ 2.455625] scsi target2:0:1: asynchronous +[ 2.466484] random: systemd-udevd: uninitialized urandom read (16 bytes read) +[ 2.466557] sd 2:0:0:0: Attached scsi generic sg0 type 0 +[ 2.469874] random: systemd-udevd: uninitialized urandom read (16 bytes read) +[ 2.472254] sd 2:0:1:0: Attached scsi generic sg1 type 0 +[ 2.475796] sd 2:0:1:0: [sdb] 20480 512-byte logical blocks: (10.5 MB/10.0 MiB) +[ 2.480854] random: systemd-udevd: uninitialized urandom read (16 bytes read) +[ 2.483694] sd 2:0:1:0: [sdb] Write Protect is off +[ 2.483705] sd 2:0:0:0: [sda] 20971520 512-byte logical blocks: (10.7 GB/10.0 GiB) +[ 2.491205] sd 2:0:1:0: [sdb] Incomplete mode parameter data +[ 2.496107] sd 2:0:1:0: [sdb] Assuming drive cache: write through +[ 2.496223] sd 2:0:0:0: [sda] Write Protect is off +[ 2.501151] sd 2:0:0:0: [sda] Incomplete mode parameter data +[ 2.503655] sd 2:0:1:0: [sdb] Attached SCSI disk +[ 2.504110] sd 2:0:0:0: [sda] Assuming drive cache: write through +[ 2.512349] sda: sda1 +[ 2.514834] sd 2:0:0:0: [sda] Attached SCSI disk +Begin: Loading essential drivers ... [ 4.120365] raid6: sse2x1 gen() 8070 MB/s +[ 4.168222] raid6: sse2x1 xor() 6016 MB/s +[ 4.216338] raid6: sse2x2 gen() 10374 MB/s +[ 4.264252] raid6: sse2x2 xor() 6295 MB/s +[ 4.312232] raid6: sse2x4 gen() 12057 MB/s +[ 4.360267] raid6: sse2x4 xor() 7732 MB/s +[ 4.408068] raid6: avx2x1 gen() 16441 MB/s +[ 4.456229] raid6: avx2x1 xor() 10055 MB/s +[ 4.504190] raid6: avx2x2 gen() 18760 MB/s +[ 4.552254] raid6: avx2x2 xor() 10226 MB/s +[ 4.600221] raid6: avx2x4 gen() 22732 MB/s +[ 4.648232] raid6: avx2x4 xor() 13132 MB/s +[ 4.649527] raid6: using algorithm avx2x4 gen() 22732 MB/s +[ 4.651588] raid6: .... xor() 13132 MB/s, rmw enabled +[ 4.653647] raid6: using avx2x2 recovery algorithm +[ 4.657327] xor: automatically using best checksumming function avx +[ 4.661178] async_tx: api initialized (async) +done. +Begin: Running /scripts/init-premount ... done. +Begin: Mounting root file system ... Begin: Running /scripts/local-top ... done. +Begin: Running /scripts/local-premount ... [ 4.729105] Btrfs loaded, crc32c=crc32c-intel +Scanning for Btrfs filesystems +done. +Warning: fsck not present, so skipping root file system +[ 4.781118] EXT4-fs (sda1): mounted filesystem with ordered data mode. Opts: (null) +done. +Begin: Running /scripts/local-bottom ... done. +Begin: Running /scripts/init-bottom ... done. +[ 5.131768] ip_tables: (C) 2000-2006 Netfilter Core Team +[ 5.152384] systemd[1]: systemd 237 running in system mode. (+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN2 +IDN -PCRE2 default-hierarchy=hybrid) +[ 5.159865] systemd[1]: Detected virtualization oracle. +[ 5.161648] systemd[1]: Detected architecture x86-64. + +Welcome to Ubuntu 18.04.3 LTS! + +[ 5.176478] systemd[1]: Set hostname to . +[ 5.185207] systemd[1]: Initializing machine ID from random generator. +[ 5.187205] systemd[1]: Installed transient /etc/machine-id file. +[ 5.680638] systemd[1]: Reached target User and Group Name Lookups. +[ OK ] Reached target User and Group Name Lookups. +[ 5.686276] systemd[1]: Set up automount Arbitrary Executable File Formats File System Automount Point. +[ OK ] Set up automount Arbitrary Executab…rmats File System Automount Point. +[ 5.698844] systemd[1]: Created slice System Slice. +[ OK ] Created slice System Slice. +[ 5.703202] systemd[1]: Created slice system-serial\x2dgetty.slice. +[ OK ] Created slice system-serial\x2dgetty.slice. +[ OK ] Listening on Journal Socket. +[ OK ] Listening on LVM2 poll daemon socket. + Starting Set the console keyboard layout... + Mounting Kernel Debug File System... + Starting Create list of required st…ce nodes for the current kernel... +[ OK ] Listening on Journal Socket (/dev/log). +[ OK ] Listening on LVM2 metadata daemon socket. + Starting Remount Root and Kernel File Systems... +[ OK ] Listening on Device-mapper event daemon FIFOs. + Starting Monitoring of LVM2 mirrors…ng dmeventd or progress polling... +[ OK ] Listening on Syslog Socket. +[ OK ] Listening on Network Service Netlink Socket. +[ OK ] Listening on udev Kernel Socket. + Starting Load Kernel Modules... +[ OK ] Listening on Journal Audit Socket. + Mounting POSIX Message Queue File System... +[ 5.813826] EXT4-fs (sda1): re-mounted. Opts: (null) + Starting Journal Service... +[ OK ] Listening on udev Control Socket. + Starting udev Coldplug all Devices... + Mounting Huge Pages File System... +[ OK ] Listening on /dev/initctl Compatibility Named Pipe. +[ OK ] Reached target System Time Synchronized. +[ OK ] Reached target Swap. +[ OK ] Started Forward Password Requests to Wall Directory Watch. +[ 5.847175] Loading iSCSI transport class v2.0-870. +[ OK ] Created slice User and Session Slice. +[ OK ] Reached target Slices. + Starting Uncomplicated firewall... +[ OK ] Mounted Kernel Debug File System. +[ OK ] Started Create list of required sta…vice nodes for the current kernel. +[ OK ] Started Remount Root and Kernel File Systems. +[ OK ] Mounted POSIX Message Queue File System. +[ OK ] Mounted Huge Pages File System. +[ OK ] Started LVM2 metadata daemon. + Starting Load/Save Random Seed... +[ 5.940173] iscsi: registered transport (tcp) + Starting Create Static Device Nodes in /dev... +[ OK ] Started Uncomplicated firewall. +[ OK ] Started udev Coldplug all Devices. +[ OK ] Started Load/Save Random Seed. +[ OK ] Started Monitoring of LVM2 mirrors,…sing dmeventd or progress polling. +[ OK ] Started Journal Service. + Starting Flush Journal to Persistent Storage... +[ 6.067247] iscsi: registered transport (iser) +[ OK ] Started Set the console keyboard layout. +[ OK ] Started Load Kernel Modules. + Starting Apply Kernel Variables... + Mounting Kernel Configuration File System... + Mounting FUSE Control File System... +[ OK ] Mounted Kernel Configuration File System. +[ OK ] Mounted FUSE Control File System. +[ 6.097472] systemd-journald[397]: Received request to flush runtime journal from PID 1 +[ OK ] Started Create Static Device Nodes in /dev. +[ OK ] Reached target Local File Systems (Pre). +[ OK ] Reached target Local File Systems. + Starting Set console font and keymap... + Starting AppArmor initialization... + Starting Tell Plymouth To Write Out Runtime Data... + Starting ebtables ruleset management... + Starting Commit a transient machine-id on disk... + Starting udev Kernel Device Manager... +[ OK ] Started Set console font and keymap. +[ OK ] Started Tell Plymouth To Write Out Runtime Data. +[ OK ] Started Apply Kernel Variables. +[ OK ] Started Flush Journal to Persistent Storage. +[ OK ] Started Commit a transient machine-id on disk. + Starting Create Volatile Files and Directories... +[ OK ] Started udev Kernel Device Manager. +[ OK ] Started Dispatch Password Requests to Console Directory Watch. +[ OK ] Reached target Local Encrypted Volumes. +[ OK ] Started Create Volatile Files and Directories. + Starting Update UTMP about System Boot/Shutdown... +[ OK ] Started ebtables ruleset management. +[ OK ] Started Update UTMP about System Boot/Shutdown. +[ OK ] Found device /dev/ttyS0. +[ OK ] Listening on Load/Save RF Kill Switch Status /dev/rfkill Watch. +[ OK ] Started AppArmor initialization. + Starting Initial cloud-init job (pre-networking)... +[ 10.488512] cloud-init[541]: Cloud-init v. 19.1-1-gbaa47854-0ubuntu1~18.04.1 running 'init-local' at Sun, 29 Sep 2019 04:37:35 +0000. Up 10.03 seconds. +[ OK ] Started Initial cloud-init job (pre-networking). +[ OK ] Reached target Network (Pre). + Starting Network Service... +[ OK ] Started Network Service. + Starting Wait for Network to be Configured... + Starting Network Name Resolution... +[ OK ] Started Network Name Resolution. +[ OK ] Reached target Host and Network Name Lookups. +[ OK ] Reached target Network. +[ OK ] Started Wait for Network to be Configured. + Starting Initial cloud-init job (metadata service crawler)... +[ 12.969172] cloud-init[659]: Cloud-init v. 19.1-1-gbaa47854-0ubuntu1~18.04.1 running 'init' at Sun, 29 Sep 2019 04:37:38 +0000. Up 12.79 seconds. +[ 12.988414] cloud-init[659]: ci-info: +++++++++++++++++++++++++++++++++++++Net device info++++++++++++++++++++++++++++++++++++++ +[ 12.994201] cloud-init[659]: ci-info: +--------+------+---------------------------+---------------+--------+-------------------+ +[ 12.999006] cloud-init[659]: ci-info: | Device | Up | Address | Mask | Scope | Hw-Address | +[ 13.004875] cloud-init[659]: ci-info: +--------+------+---------------------------+---------------+--------+-------------------+ +[ 13.020787] cloud-init[659]: ci-info: | enp0s3 | True | 10.0.2.15 | 255.255.255.0 | global | 02:ee:0a:3b:45:98 | +[ 13.025532] cloud-init[659]: ci-info: | enp0s3 | True | fe80::ee:aff:fe3b:4598/64 | . | link | 02:ee:0a:3b:45:98 | +[ 13.031006] cloud-init[659]: ci-info: | lo | True | 127.0.0.1 | 255.0.0.0 | host | . | +[ 13.035312] cloud-init[659]: ci-info: | lo | True | ::1/128 | . | host | . | +[ 13.039598] cloud-init[659]: ci-info: +--------+------+---------------------------+---------------+--------+-------------------+ +[ 13.043951] cloud-init[659]: ci-info: ++++++++++++++++++++++++++++Route IPv4 info+++++++++++++++++++++++++++++ +[ 13.047653] cloud-init[659]: ci-info: +-------+-------------+----------+-----------------+-----------+-------+ +[ 13.051037] cloud-init[659]: ci-info: | Route | Destination | Gateway | Genmask | Interface | Flags | +[ 13.054622] cloud-init[659]: ci-info: +-------+-------------+----------+-----------------+-----------+-------+ +[ 13.058025] cloud-init[659]: ci-info: | 0 | 0.0.0.0 | 10.0.2.2 | 0.0.0.0 | enp0s3 | UG | +[ 13.064532] cloud-init[659]: ci-info: | 1 | 10.0.2.0 | 0.0.0.0 | 255.255.255.0 | enp0s3 | U | +[ 13.068647] cloud-init[659]: ci-info: | 2 | 10.0.2.2 | 0.0.0.0 | 255.255.255.255 | enp0s3 | UH | +[ 13.072784] cloud-init[659]: ci-info: +-------+-------------+----------+-----------------+-----------+-------+ +[ 13.077092] cloud-init[659]: ci-info: +++++++++++++++++++Route IPv6 info+++++++++++++++++++ +[ 13.081258] cloud-init[659]: ci-info: +-------+-------------+---------+-----------+-------+ +[ 13.084694] cloud-init[659]: ci-info: | Route | Destination | Gateway | Interface | Flags | +[ 13.088479] cloud-init[659]: ci-info: +-------+-------------+---------+-----------+-------+ +[ 13.092360] cloud-init[659]: ci-info: | 1 | fe80::/64 | :: | enp0s3 | U | +[ 13.096047] cloud-init[659]: ci-info: | 3 | local | :: | enp0s3 | U | +[ 13.108512] cloud-init[659]: ci-info: | 4 | ff00::/8 | :: | enp0s3 | U | +[ 13.111402] cloud-init[659]: ci-info: +-------+-------------+---------+-----------+-------+ +[ 14.801704] cloud-init[659]: Generating public/private rsa key pair. +[ 14.804063] cloud-init[659]: Your identification has been saved in /etc/ssh/ssh_host_rsa_key. +[ 14.807013] cloud-init[659]: Your public key has been saved in /etc/ssh/ssh_host_rsa_key.pub. +[ 14.810006] cloud-init[659]: The key fingerprint is: +[ 14.811799] cloud-init[659]: SHA256:c2pCGhDRoUfEBnPbtaYdQ3UOxcvdbTfhVuLtz0dkmho root@ubuntu-bionic +[ 14.814850] cloud-init[659]: The key's randomart image is: +[ 14.816758] cloud-init[659]: +---[RSA 2048]----+ +[ 14.818333] cloud-init[659]: | =*=. o.ooo | +[ 14.820006] cloud-init[659]: | *+o o . +. ...| +[ 14.821832] cloud-init[659]: | o.o . = ..+.++| +[ 14.823443] cloud-init[659]: | o + o o o+O| +[ 14.825068] cloud-init[659]: | . o S . .Bo| +[ 14.826979] cloud-init[659]: | + + E o o| +[ 14.828571] cloud-init[659]: | . . o o o.| +[ 14.830148] cloud-init[659]: | o . +| +[ 14.831813] cloud-init[659]: | .| +[ 14.833704] cloud-init[659]: +----[SHA256]-----+ +[ 14.835513] cloud-init[659]: Generating public/private dsa key pair. +[ 14.837922] cloud-init[659]: Your identification has been saved in /etc/ssh/ssh_host_dsa_key. +[ 14.841095] cloud-init[659]: Your public key has been saved in /etc/ssh/ssh_host_dsa_key.pub. +[ 14.848419] cloud-init[659]: The key fingerprint is: +[ 14.851284] cloud-init[659]: SHA256:MJXByZgiy2fMsy8Xn2zy9OmXy933B3UshTKr+5h33hk root@ubuntu-bionic +[ 14.855140] cloud-init[659]: The key's randomart image is: +[ 14.857583] cloud-init[659]: +---[DSA 1024]----+ +[ 14.859572] cloud-init[659]: | =o+ . | +[ 14.861674] cloud-init[659]: | . . o.= o . .| +[ 14.864198] cloud-init[659]: | . = .o + o | +[ 14.866677] cloud-init[659]: | o * o . . +| +[ 14.868652] cloud-init[659]: | o o S . o.| +[ 14.870808] cloud-init[659]: | . . . . | +[ 14.873495] cloud-init[659]: | . +.. . . E | +[ 14.875623] cloud-init[659]: | . +.=..=+..o=| +[ 14.877971] cloud-init[659]: | o +..*+++o.B| +[ 14.892804] cloud-init[659]: +----[SHA256]-----+ +[ 14.895209] cloud-init[659]: Generating public/private ecdsa key pair. +[ 14.898389] cloud-init[659]: Your identification has been saved in /etc/ssh/ssh_host_ecdsa_key. +[ 14.902293] cloud-init[659]: Your public key has been saved in /etc/ssh/ssh_host_ecdsa_key.pub. +[ 14.906277] cloud-init[659]: The key fingerprint is: +[ 14.908735] cloud-init[659]: SHA256:pO6EMl9WjroVoRc7HUT6TPHWmIwrLWM7cIAbiERyxQY root@ubuntu-bionic +[ 14.913129] cloud-init[659]: The key's randomart image is: +[ 14.915736] cloud-init[659]: +---[ECDSA 256]---+ +[ 14.917760] cloud-init[659]: |ooE+. .+ | +[ 14.919668] cloud-init[659]: |+o .o o = + | +[ 14.921986] cloud-init[659]: |o o.. + = * . | +[ 14.924110] cloud-init[659]: | o o % + | +[ 14.926792] cloud-init[659]: | . o % S | +[ 14.929165] cloud-init[659]: | B @ | +[ 14.931706] cloud-init[659]: | o . X . | +[ 14.938220] cloud-init[659]: | + B . | +[ 14.940944] cloud-init[659]: | +.. | +[ OK ] Started Initial cloud-init job (metadata service crawler). +[ 14.968369] cloud-init[659]: +----[SHA256]-----+ +[ 14.970927] cloud-init[659]: Generating public/private ed25519 key pair. +[ 14.973333] cloud-init[659]: Your identification has been saved in /etc/ssh/ssh_host_ed25519_key.[ OK ] Reached target Cloud-config availability. +[ OK ] Reached target Network is Online. + +[ 14.985253] cloud-init[659]: Your public key has been saved in /etc/ssh/ssh_host_ed25519_key.pub. +[ 14.988429] cloud-init[659]: The key fingerprint is: +[ 14.990670] cloud-init[659]: SHA256:DRCkk4eijXFIbhkPmPoF+gSbJ3ncPFySperwkyCRpI0 root@ubuntu-bionic[ OK ] Reached target Remote File Systems (Pre). +[ OK ] Reached target Remote File Systems. + + Starting Availability of block devices... +[ 15.016115] cloud-init[659]: The key's randomart image is: +[ OK ] Reached target System Initialization. +[ OK ] Started Daily apt download activities. +[ OK [ 15.018265] cloud-init[659]: +--[ED25519 256]--+ +] Started Daily Cleanup of Temporary Directories. +[ 15.034267] cloud-init[659]: |.* +=. | +[ 15.035916] cloud-init[659]: |O=* o=.. | Starting LXD - unix socket. +[ OK ] Listening on D-Bus System Message Bus Socket. +[ OK ] Started ACPI Events Check. +[ OK ] Listening on ACPID Listen Socket. +[ OK ] Started Daily apt upgrade and clean activities. +[ OK ] Reached target Paths. +[ OK ] Started Discard unused blocks once a week. + Starting Socket activation for snappy daemon. +[ OK ] Listening on UUID daemon activation socket. +[ OK ] Started Message of the Day. +[ OK ] Reached target Timers. +[ OK ] Listening on Open-iSCSI iscsid Socket. + +[ OK ] Started Availability of block devices.[ 15.080554] cloud-init[659]: |E@+**o. . | +[ 15.081867] cloud-init[659]: |OB=o*o o | +[ 15.082301] cloud-init[659]: |*Bo. . S . | +[ 15.082380] cloud-init[659]: |.=o. | +[ 15.082428] cloud-init[659]: | = | +[ 15.082593] cloud-init[659]: | . | +[ 15.082950] cloud-init[659]: | | +[ 15.083005] cloud-init[659]: +----[SHA256]-----+ + +[ OK ] Listening on LXD - unix socket. +[ OK ] Listening on Socket activation for snappy daemon. +[ OK ] Reached target Sockets. +[ OK ] Reached target Basic System. + Starting System Logging Service... +[ OK ] Started FUSE filesystem for LXC. + Starting LSB: Record successful boot for GRUB... + Starting Accounts Service... +[ OK ] Started Regular background program processing daemon. +[ OK ] Started irqbalance daemon. + Starting LSB: automatic crash report generation... +[ OK ] Started D-Bus System Message Bus. + Starting Dispatcher daemon for systemd-networkd... + Starting Permit User Sessions... + Starting LXD - container startup/shutdown... +[ OK ] Started Deferred execution scheduler. + Starting Login Service... + Starting Snappy daemon... + Starting Pollinate to seed the pseudo random number generator... + Starting Virtualbox guest utils... +[ OK ] Started System Logging Service. +[ OK ] Started Permit User Sessions. +[ OK ] Started Login Service. +[ OK ] Started Unattended Upgrades Shutdown. + Starting Authorization Manager... + Starting Hold until boot process finishes up... + Starting Terminate Plymouth Boot Screen... +[ OK ] Started Hold until boot process finishes up. +[ OK ] Started Serial Getty on ttyS0. + Starting Set console scheme... +[ OK ] Started Terminate Plymouth Boot Screen. +[ OK ] Started LSB: automatic crash report generation. +[ OK ] Started Set console scheme. +[ OK ] Created slice system-getty.slice. +[ OK ] Started Getty on tty1. +[ OK ] Reached target Login Prompts. +[ OK ] Started Authorization Manager. +[ OK ] Started Accounts Service. +[ OK ] Started LSB: Record successful boot for GRUB. +[ OK ] Started Virtualbox guest utils. +[ OK ] Started Dispatcher daemon for systemd-networkd. +[ OK ] Started LXD - container startup/shutdown. +[ OK ] Started Snappy daemon. + Starting Wait until snapd is fully seeded... +[ OK ] Started Pollinate to seed the pseudo random number generator. + Starting OpenBSD Secure Shell server... +[ OK ] Started OpenBSD Secure Shell server. +[ OK ] Created slice User Slice of vagrant. + Starting User Manager for UID 1000... +[ OK ] Started Session 1 of user vagrant. +[ OK ] Started User Manager for UID 1000. +[ OK ] Started Wait until snapd is fully seeded. +[ OK ] Reached target Multi-User System. +[ OK ] Reached target Graphical Interface. + Starting Update UTMP about System Runlevel Changes... + Starting Apply the settings specified in cloud-config... +[ OK ] Started Update UTMP about System Runlevel Changes. + +Ubuntu 18.04.3 LTS ubuntu-bionic ttyS0 + +ubuntu-bionic login: [ 22.238032] cloud-init[1248]: Cloud-init v. 19.1-1-gbaa47854-0ubuntu1~18.04.1 running 'modules:config' at Sun, 29 Sep 2019 04:37:46 +0000. Up 20.92 seconds. +ci-info: no authorized ssh keys fingerprints found for user ubuntu. +<14>Sep 29 04:37:48 ec2: +<14>Sep 29 04:37:48 ec2: ############################################################# +<14>Sep 29 04:37:48 ec2: -----BEGIN SSH HOST KEY FINGERPRINTS----- +<14>Sep 29 04:37:48 ec2: 1024 SHA256:MJXByZgiy2fMsy8Xn2zy9OmXy933B3UshTKr+5h33hk root@ubuntu-bionic (DSA) +<14>Sep 29 04:37:48 ec2: 256 SHA256:pO6EMl9WjroVoRc7HUT6TPHWmIwrLWM7cIAbiERyxQY root@ubuntu-bionic (ECDSA) +<14>Sep 29 04:37:48 ec2: 256 SHA256:DRCkk4eijXFIbhkPmPoF+gSbJ3ncPFySperwkyCRpI0 root@ubuntu-bionic (ED25519) +<14>Sep 29 04:37:48 ec2: 2048 SHA256:c2pCGhDRoUfEBnPbtaYdQ3UOxcvdbTfhVuLtz0dkmho root@ubuntu-bionic (RSA) +<14>Sep 29 04:37:49 ec2: -----END SSH HOST KEY FINGERPRINTS----- +<14>Sep 29 04:37:49 ec2: ############################################################# +-----BEGIN SSH HOST KEY KEYS----- +ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBL1FoJIMczy8dfbRV3RzzcLXkRT/ouhH2qd6HDGf+Akmq+66qodZ0SAF24sVKe32obV1l1ajbBfVR5FpXdvZ+l0= root@ubuntu-bionic +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAO/aUSNVrB6FQOHxHf2DXC19OlkZIgLMoAi8iVDNNpN root@ubuntu-bionic +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/EIXVrXLv5Nzfe/cqvE4IBOGjA097OyEJSTB/chiuHlw/YPuVtTsDRDEOSIvjPGsjzQG/PBzgdJx4nnL1+xV2WUVNZvFDQUmXSyCRuAxPZSO9FwkfLb6ebloPoyuojmiMcqFuhb+ZTiGmJwf5LoPzz9xF8qxrsD1IGadfw8GINfhERoQRaP6rM/lPbIQgnwcK03oPlCs35NMAa09nQ4Qs0sUPEjt+IMOCxifCqoCpsHUMT4bU/FFxQ1c9nr39AuCegjILGM6mtMP+Wutgbpg4ZxpJ7e3uO8J5jrTZa9U13bSzpO7JUSJrri1ol5Lsx1w6S5rVZqJhpyNFjIzsdnXR root@ubuntu-bionic +-----END SSH HOST KEY KEYS----- +[ 23.573587] cloud-init[1370]: Cloud-init v. 19.1-1-gbaa47854-0ubuntu1~18.04.1 running 'modules:final' at Sun, 29 Sep 2019 04:37:48 +0000. Up 23.13 seconds. +[ 23.573721] cloud-init[1370]: ci-info: no authorized ssh keys fingerprints found for user ubuntu. +[ 23.588105] cloud-init[1370]: Cloud-init v. 19.1-1-gbaa47854-0ubuntu1~18.04.1 finished at Sun, 29 Sep 2019 04:37:49 +0000. Datasource DataSourceNoCloud [seed=/dev/sdb][dsmode=net]. Up 23.54 seconds diff --git a/packages/wings/web/index.html b/packages/wings/web/index.html new file mode 100644 index 00000000..c0300979 --- /dev/null +++ b/packages/wings/web/index.html @@ -0,0 +1,13 @@ + + + + + + + Angel Wings + + + +

Hello!!!

+ + \ No newline at end of file diff --git a/packages/wings/web/site.css b/packages/wings/web/site.css new file mode 100644 index 00000000..c2140b8b --- /dev/null +++ b/packages/wings/web/site.css @@ -0,0 +1,3 @@ +h1 { + color: blue; +} \ No newline at end of file