Skip to content
This repository has been archived by the owner on Feb 11, 2024. It is now read-only.

fix: returning values instead of pointers from cronet #7

Merged
merged 9 commits into from
Jul 6, 2021
3 changes: 3 additions & 0 deletions .github/workflows/test-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ jobs:
- id: get_binaries
name: Download Cronet Binaries
run: dart run cronet:setup
- id: build_wrapper
name: Build Cronet Wrapper Dylib
run: dart run cronet:setup build
- name: Run VM tests
run: dart test --platform vm
if: always() && steps.install.outcome == 'success'
14 changes: 9 additions & 5 deletions bin/setup.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,12 @@ void buildWrapper() {
Directory.current = Directory(wrapperPath);
logger.stdout('Building Wrapper...');
try {
final result = Process.runSync(
'cmake', ['CMakeLists.txt', '-B', 'out/${Platform.operatingSystem}']);
final result = Process.runSync('cmake', [
'CMakeLists.txt',
'-B',
'out/${Platform.operatingSystem}',
'-DCMAKE_BUILD_TYPE=Release'
]);
print(result.stdout);
print(result.stderr);
} catch (error) {
Expand All @@ -95,8 +99,8 @@ void buildWrapper() {
}
return;
}
var result =
Process.runSync('cmake', ['--build', 'out/${Platform.operatingSystem}']);
var result = Process.runSync('cmake',
['--build', 'out/${Platform.operatingSystem}', '--config', 'Release']);
print(result.stdout);
print(result.stderr);
if (result.exitCode != 0) return;
Expand All @@ -105,7 +109,7 @@ void buildWrapper() {
Directory(moveLocation).createSync(recursive: true);
final buildOutputPath = Platform.isLinux
? '$wrapperPath/out/${Platform.operatingSystem}/${getWrapperName()}'
: '$wrapperPath\\out\\${Platform.operatingSystem}\\Debug\\${getWrapperName()}';
: '$wrapperPath\\out\\${Platform.operatingSystem}\\Release\\${getWrapperName()}';
File(buildOutputPath).copySync('$moveLocation/${getWrapperName()}');
logger.stdout(
'${ansi.green}Wrapper moved to $moveLocation. Success!${ansi.none}');
Expand Down
4 changes: 3 additions & 1 deletion example_dart/bin/example_dart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ void main(List<String> args) {
for (var i = 0; i < 3; i++) {
// Demo - with concurrent requests
client
.getUrl(Uri.parse('https://postman-echo.com/headers'))
.getUrl(Uri.parse('https://example.com'))
.then((HttpClientRequest request) {
if (i == 2) {
client.close(); // We will shut down the client after 3 connections.
Expand All @@ -21,6 +21,8 @@ void main(List<String> args) {
print(contents);
}, onDone: () {
print('cronet implemenation took: ${stopwatch.elapsedMilliseconds} ms');
}, onError: (Object e) {
print(e);
});
});
}
Expand Down
1 change: 1 addition & 0 deletions lib/src/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const tag = 'binaries-v0.0.1';
const cronetBinaryUrl =
'https://github.com/google/cronet.dart/releases/download/$tag/';
const cronetVersion = "86.0.4240.198";
const wrapperVersion = "1.0";

const binaryStorageDir = '.dart_tool/cronet/';

Expand Down
17 changes: 16 additions & 1 deletion lib/src/globals.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,24 @@

import 'dart:ffi';

import 'package:cli_util/cli_logging.dart';
import 'package:ffi/ffi.dart';

import 'constants.dart';
import 'dylib_handler.dart';
import 'third_party/cronet/generated_bindings.dart';
import 'wrapper/generated_bindings.dart';

Wrapper loadAndInitWrapper() {
final wrapper = Wrapper(loadWrapper());
if (wrapperVersion != wrapper.VersionString().cast<Utf8>().toDartString()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're doing just a comparison, there is no reason to have a major and minor revision. Then we can just have a simple number.

In some cases an API gets extra functionality, in those cases you only bump the minor revision. And you can keep using the previous binary if you're never calling the new functionality with dart:ffi. But if this wrapper is set up in a way that we're most likely always have to do a major version increase, we might as well just have only major version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keeping it for version only. Let's plan to move to major.minor format when the wrapper is little more stable.

final logger = Logger.standard();
final ansi = Ansi(Ansi.terminalSupportsAnsi);
logger.stderr('${ansi.red}Wrapper is outdated.${ansi.none}');
logger.stdout('Update wrapper by running: '
'${ansi.yellow}dart run cronet:setup${ansi.none}');
throw Error();
}
// Initialize Dart Native API dynamically.
wrapper.InitDartApiDL(NativeApi.initializeApiDLData);
// Registers few cronet functions that are required by the wrapper.
Expand All @@ -18,7 +30,10 @@ Wrapper loadAndInitWrapper() {
cronet.addresses.Cronet_Engine_Shutdown.cast(),
cronet.addresses.Cronet_Engine_Destroy.cast(),
cronet.addresses.Cronet_Buffer_Create.cast(),
cronet.addresses.Cronet_Buffer_InitWithAlloc.cast());
cronet.addresses.Cronet_Buffer_InitWithAlloc.cast(),
cronet.addresses.Cronet_UrlResponseInfo_http_status_code_get.cast(),
cronet.addresses.Cronet_Error_message_get.cast(),
cronet.addresses.Cronet_UrlResponseInfo_http_status_text_get.cast());
// Registers few cronet functions that are required by the executor
// run from the wrapper for executing network requests.
// Casting because of https://github.com/dart-lang/ffigen/issues/22
Expand Down
63 changes: 33 additions & 30 deletions lib/src/http_callback_handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,22 @@ class CallbackHandler {
}

/// Checks status of an URL response.
int statusChecker(Pointer<Cronet_UrlResponseInfo> respInfoPtr, int lBound,
int uBound, void Function() callback) {
final respCode =
cronet.Cronet_UrlResponseInfo_http_status_code_get(respInfoPtr);
bool statusChecker(int respCode, Pointer<Utf8> status, int lBound, int uBound,
void Function() callback) {
if (!(respCode >= lBound && respCode <= uBound)) {
// If NOT in range.
if (status == nullptr) {
_controller.addError(HttpException('$respCode'));
} else {
final statusStr = status.toDartString();
_controller.addError(
HttpException(statusStr.isNotEmpty ? statusStr : '$respCode'));
malloc.free(status);
}
callback();
final exception = HttpException(
cronet.Cronet_UrlResponseInfo_http_status_text_get(respInfoPtr)
.cast<Utf8>()
.toDartString());
_controller.addError(exception);
_controller.close();
return false;
}
return respCode;
return true;
}

/// This listens to the messages sent by native cronet library.
Expand All @@ -100,14 +101,16 @@ class CallbackHandler {
switch (reqMessage.method) {
case 'OnRedirectReceived':
{
final newUrlPtr = Pointer.fromAddress(args[0]).cast<Utf8>();
log('New Location: '
'${Pointer.fromAddress(args[0]).cast<Utf8>().toDartString()}');
'${newUrlPtr.toDartString()}');
malloc.free(newUrlPtr);
// If NOT a 3XX status code, throw Exception.
statusChecker(
Pointer.fromAddress(args[1]).cast<Cronet_UrlResponseInfo>(),
300,
399,
() => cleanUpRequest(reqPtr, cleanUpClient));
final status = statusChecker(args[1], Pointer.fromAddress(args[2]),
300, 399, () => cronet.Cronet_UrlRequest_Cancel(reqPtr));
if (!status) {
break;
}
if (followRedirects && maxRedirects > 0) {
final res = cronet.Cronet_UrlRequest_FollowRedirect(reqPtr);
if (res != Cronet_RESULT.Cronet_RESULT_SUCCESS) {
Expand All @@ -125,12 +128,12 @@ class CallbackHandler {
case 'OnResponseStarted':
{
// If NOT a 1XX or 2XX status code, throw Exception.
statusChecker(
Pointer.fromAddress(args[0]).cast<Cronet_UrlResponseInfo>(),
100,
299,
() => cleanUpRequest(reqPtr, cleanUpClient));
final status = statusChecker(args[0], Pointer.fromAddress(args[2]),
100, 299, () => cronet.Cronet_UrlRequest_Cancel(reqPtr));
log('Response started');
if (!status) {
break;
}
final res = cronet.Cronet_UrlRequest_Read(
reqPtr, Pointer.fromAddress(args[1]).cast<Cronet_Buffer>());
if (res != Cronet_RESULT.Cronet_RESULT_SUCCESS) {
Expand All @@ -146,14 +149,16 @@ class CallbackHandler {
case 'OnReadCompleted':
{
final request = Pointer<Cronet_UrlRequest>.fromAddress(args[0]);
final info = Pointer<Cronet_UrlResponseInfo>.fromAddress(args[1]);
final buffer = Pointer<Cronet_Buffer>.fromAddress(args[2]);
final bytesRead = args[3];

log('Recieved: $bytesRead');
// If NOT a 1XX or 2XX status code, throw Exception.
statusChecker(
info, 100, 299, () => cleanUpRequest(reqPtr, cleanUpClient));
final status = statusChecker(args[1], Pointer.fromAddress(args[4]),
100, 299, () => cronet.Cronet_UrlRequest_Cancel(reqPtr));
if (!status) {
break;
}
final data = cronet.Cronet_Buffer_GetData(buffer)
.cast<Uint8>()
.asTypedList(bytesRead);
Expand All @@ -169,11 +174,9 @@ class CallbackHandler {
// In case of network error, we will shut down everything.
case 'OnFailed':
{
final errorPtr = Pointer.fromAddress(args[0]).cast<Cronet_Error>();
final error = Pointer.fromAddress(
cronet.Cronet_Error_message_get(errorPtr).address)
.cast<Utf8>()
.toDartString();
final errorStrPtr = Pointer.fromAddress(args[0]).cast<Utf8>();
final error = errorStrPtr.toDartString();
malloc.free(errorStrPtr);
cleanUpRequest(reqPtr, cleanUpClient);
_controller.addError(HttpException(error));
_controller.close();
Expand Down
4 changes: 4 additions & 0 deletions lib/src/http_client_request.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ abstract class HttpClientRequest implements io.IOSink {

/// Follow the redirects.
bool get followRedirects;
set followRedirects(bool follow);

/// Maximum numbers of redirects to follow.
/// Have no effect if [followRedirects] is set to false.
int get maxRedirects;
set maxRedirects(int redirects);

/// The uri of the request.
Uri get uri;
Expand Down Expand Up @@ -149,6 +151,7 @@ class HttpClientRequestImpl implements HttpClientRequest {
/// Follow the redirects.
@override
bool get followRedirects => _callbackHandler.followRedirects;
@override
set followRedirects(bool follow) {
_callbackHandler.followRedirects = follow;
}
Expand All @@ -157,6 +160,7 @@ class HttpClientRequestImpl implements HttpClientRequest {
/// Have no effect if [followRedirects] is set to false.
@override
int get maxRedirects => _callbackHandler.maxRedirects;
@override
set maxRedirects(int redirects) {
_callbackHandler.maxRedirects = redirects;
}
Expand Down
3 changes: 3 additions & 0 deletions lib/src/third_party/cronet/ffigen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ functions:
- 'Cronet_Engine_Destroy'
- 'Cronet_Buffer_Create'
- 'Cronet_Buffer_InitWithAlloc'
- 'Cronet_UrlResponseInfo_http_status_code_get'
- 'Cronet_Error_message_get'
- 'Cronet_UrlResponseInfo_http_status_text_get'
# For executor.
- 'Cronet_Executor_CreateWith'
- 'Cronet_Executor_SetClientContext'
Expand Down
28 changes: 21 additions & 7 deletions lib/src/third_party/cronet/generated_bindings.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1691,7 +1691,7 @@ class Cronet {
}

late final _Cronet_Error_message_get_ptr =
_lookup<ffi.NativeFunction<_c_Cronet_Error_message_get>>(
_lookup<ffi.NativeFunction<Native_Cronet_Error_message_get>>(
'Cronet_Error_message_get');
late final _dart_Cronet_Error_message_get _Cronet_Error_message_get =
_Cronet_Error_message_get_ptr.asFunction<
Expand Down Expand Up @@ -3006,7 +3006,8 @@ class Cronet {
}

late final _Cronet_UrlResponseInfo_http_status_code_get_ptr = _lookup<
ffi.NativeFunction<_c_Cronet_UrlResponseInfo_http_status_code_get>>(
ffi.NativeFunction<
Native_Cronet_UrlResponseInfo_http_status_code_get>>(
'Cronet_UrlResponseInfo_http_status_code_get');
late final _dart_Cronet_UrlResponseInfo_http_status_code_get
_Cronet_UrlResponseInfo_http_status_code_get =
Expand All @@ -3022,7 +3023,8 @@ class Cronet {
}

late final _Cronet_UrlResponseInfo_http_status_text_get_ptr = _lookup<
ffi.NativeFunction<_c_Cronet_UrlResponseInfo_http_status_text_get>>(
ffi.NativeFunction<
Native_Cronet_UrlResponseInfo_http_status_text_get>>(
'Cronet_UrlResponseInfo_http_status_text_get');
late final _dart_Cronet_UrlResponseInfo_http_status_text_get
_Cronet_UrlResponseInfo_http_status_text_get =
Expand Down Expand Up @@ -4678,6 +4680,18 @@ class _SymbolAddresses {
get Cronet_Engine_Destroy => _library._Cronet_Engine_Destroy_ptr;
ffi.Pointer<ffi.NativeFunction<Native_Cronet_Engine_Shutdown>>
get Cronet_Engine_Shutdown => _library._Cronet_Engine_Shutdown_ptr;
ffi.Pointer<ffi.NativeFunction<Native_Cronet_Error_message_get>>
get Cronet_Error_message_get => _library._Cronet_Error_message_get_ptr;
ffi.Pointer<
ffi.NativeFunction<
Native_Cronet_UrlResponseInfo_http_status_code_get>>
get Cronet_UrlResponseInfo_http_status_code_get =>
_library._Cronet_UrlResponseInfo_http_status_code_get_ptr;
ffi.Pointer<
ffi.NativeFunction<
Native_Cronet_UrlResponseInfo_http_status_text_get>>
get Cronet_UrlResponseInfo_http_status_text_get =>
_library._Cronet_UrlResponseInfo_http_status_text_get_ptr;
}

class Cronet_Buffer extends ffi.Opaque {}
Expand Down Expand Up @@ -6048,7 +6062,7 @@ typedef _dart_Cronet_Error_error_code_get = int Function(
ffi.Pointer<Cronet_Error> self,
);

typedef _c_Cronet_Error_message_get = ffi.Pointer<ffi.Int8> Function(
typedef Native_Cronet_Error_message_get = ffi.Pointer<ffi.Int8> Function(
ffi.Pointer<Cronet_Error> self,
);

Expand Down Expand Up @@ -6757,16 +6771,16 @@ typedef _dart_Cronet_UrlResponseInfo_url_chain_clear = void Function(
ffi.Pointer<Cronet_UrlResponseInfo> self,
);

typedef _c_Cronet_UrlResponseInfo_http_status_code_get = ffi.Int32 Function(
typedef Native_Cronet_UrlResponseInfo_http_status_code_get = ffi.Int32 Function(
ffi.Pointer<Cronet_UrlResponseInfo> self,
);

typedef _dart_Cronet_UrlResponseInfo_http_status_code_get = int Function(
ffi.Pointer<Cronet_UrlResponseInfo> self,
);

typedef _c_Cronet_UrlResponseInfo_http_status_text_get = ffi.Pointer<ffi.Int8>
Function(
typedef Native_Cronet_UrlResponseInfo_http_status_text_get
= ffi.Pointer<ffi.Int8> Function(
ffi.Pointer<Cronet_UrlResponseInfo> self,
);

Expand Down