Restored FFI to working order (#28)

* Restored FFI to working order

* Disabled incompatible tests, fixed string conversion

* Use extension_loaded instead of checking PHP version

* Added better checks for FFI

* Do not build FFI deps if no FFI is present
This commit is contained in:
Justin Boswell
2021-06-16 11:26:31 -07:00
committed by GitHub
parent d2546e616d
commit f6f9a6b349
12 changed files with 172 additions and 20 deletions
+1 -1
View File
@@ -13,6 +13,6 @@ abstract class Signing extends NativeResource {
function($result, $error_code) use ($on_complete) {
$signing_result = SigningResult::fromNative($result);
$on_complete($signing_result, $error_code);
});
}, null);
}
}
+25 -2
View File
@@ -24,6 +24,14 @@ final class CRT {
if (is_null(self::$impl)) {
// Figure out what backends are/should be available
$backends = ['Extension'];
if (extension_loaded('ffi')) {
$backends = ['Extension', 'FFI'];
if (getenv('AWS_CRT_PHP_EXTENSION')) {
$backends = ['Extension'];
} else if (getenv('AWS_CRT_PHP_FFI')) {
$backends = ['FFI'];
}
}
// Try to load each backend, give up if none succeed
$exceptions = [];
@@ -31,6 +39,7 @@ final class CRT {
try {
$backend = 'AWS\\CRT\\Internal\\' . $backend;
self::$impl = new $backend();
break;
} catch (RuntimeException $rex) {
array_push($exceptions, $rex);
}
@@ -67,6 +76,20 @@ final class CRT {
}
}
/**
* @return bool true if using PHP FFI (PHP 7.4+)
*/
public static function isFFI() {
return self::isLoaded() && strstr(get_class(self::$impl), 'FFI');
}
/**
* @return bool true if using PHP Extension awscrt
*/
public static function isExtension() {
return self::isLoaded() && strstr(get_class(self::$impl), 'Extension');
}
/**
* @return integer last error code reported within the CRT
*/
@@ -319,7 +342,7 @@ final class CRT {
$signing_result, $http_message);
}
function sign_request_aws($signable, $signing_config, $on_complete) {
return self::$impl->aws_crt_sign_request_aws($signable, $signing_config, $on_complete);
function sign_request_aws($signable, $signing_config, $on_complete, $user_data) {
return self::$impl->aws_crt_sign_request_aws($signable, $signing_config, $on_complete, $user_data);
}
}
+82
View File
@@ -0,0 +1,82 @@
<?php
namespace AWS\CRT\Internal;
use Exception;
use RuntimeException;
/**
* @internal
* Forwards calls on to libaws-crt-ffi via FFI
*/
final class FFI {
private static $ffi = null;
private static $refcount = 0;
function __construct() {
if (is_null(self::$ffi)) {
try {
$shlib_ext = 'so';
$uname_s = php_uname('s');
if ($uname_s == 'Darwin') {
$shlib_ext = 'dylib';
} else if ($uname_s == 'WINNT') {
$shlib_ext = 'dll';
}
self::$ffi = \FFI::cdef(
file_get_contents(__DIR__ . "/../../../api.h"),
__DIR__ . "/../../../libaws-crt-ffi." . $shlib_ext);
self::init();
} catch (Exception $e) {
throw new RuntimeException('Exception while initializing CRT via FFI', 0, $e);
}
}
++self::$refcount;
}
function __destruct() {
if (--self::$refcount == 0) {
self::clean_up();
self::$ffi = null;
}
}
/**
* Forwards any call made on this object to the FFI function of the
* same name with the supplied arguments. Argument type hinting and checking
* occurs at the CRT wrapper.
*/
function __call(string $name, $args) {
// Expand strings to (string, length)
$ffi_args =[];
foreach ($args as $arg) {
if (is_string($arg)) {
$len = strlen($arg);
if ($len > 0) {
$uint8_t = \FFI::type('uint8_t');
$uint8_array = \FFI::arrayType($uint8_t, [$len]);
$buf = \FFI::new($uint8_array);
\FFI::memcpy($buf, $arg, $len);
$ffi_args [] = $buf;
$ffi_args [] = $len;
} else {
$ffi_args [] = null;
$ffi_args [] = 0;
}
} else if (is_resource($arg)) {
throw new RuntimeException("Resource types are not supported for FFI");
} else {
$ffi_args []= $arg;
}
}
return call_user_func_array([self::$ffi, $name], $ffi_args);
}
private static function init() {
return self::$ffi->aws_crt_init();
}
private static function clean_up() {
return self::$ffi->aws_crt_clean_up();
}
}