mirror of
https://github.com/frida/frida-core.git
synced 2026-11-08 08:05:58 -10:00
Compare commits
No files matched your search
@@ -42,7 +42,9 @@ jobs:
|
||||
run: sudo security authorizationdb write system.privilege.taskport allow
|
||||
- name: Install gcc-multilib
|
||||
if: matrix.id == 'linux-x86'
|
||||
run: sudo apt-get install gcc-multilib lib32stdc++-11-dev
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc-multilib lib32stdc++-11-dev
|
||||
- name: Build
|
||||
if: ${{ startsWith(matrix.id, 'windows-') }}
|
||||
run: |
|
||||
@@ -87,7 +89,9 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install toolchain
|
||||
run: sudo apt-get install ${{ matrix.pkg }}
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install ${{ matrix.pkg }}
|
||||
- name: Build
|
||||
run: |
|
||||
./configure ${{ matrix.opts }} ${{ env.FRIDA_CORE_OPTIONS }}
|
||||
@@ -177,6 +181,7 @@ jobs:
|
||||
tar -C /tmp/pkg -czf /tmp/runner.tar.gz .
|
||||
- name: Test on Corellium iOS device
|
||||
if: matrix.id == 'ios-arm64'
|
||||
continue-on-error: true
|
||||
uses: frida/corellium-action@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -192,6 +197,7 @@ jobs:
|
||||
./frida-tests
|
||||
- name: Test on Corellium Android device
|
||||
if: matrix.id == 'android-arm64'
|
||||
continue-on-error: true
|
||||
uses: frida/corellium-action@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
+7
-5
@@ -432,7 +432,7 @@ def compile(privdir: Path, state: State):
|
||||
path = Path(raw_path)
|
||||
if not path.is_absolute():
|
||||
path = Path(os.path.relpath(workdir / path, top_builddir))
|
||||
input_entries.append(quote(path.as_posix()))
|
||||
input_entries.append(escape_depfile_path(path.as_posix()))
|
||||
depfile_lines.append(f"{output_relpath}: {' '.join(input_entries)}")
|
||||
|
||||
(state.builddir / DEPFILE_FILENAME).write_text("\n".join(depfile_lines), encoding="utf-8")
|
||||
@@ -480,6 +480,10 @@ def option_should_be_forwarded(k: "OptionKey",
|
||||
return False
|
||||
if not str(v.value):
|
||||
return False
|
||||
if not is_for_child and role == "subproject" and k.subproject in {"", our_project_id}:
|
||||
if not coredata.BUILTIN_OPTIONS[k.as_root()].yielding:
|
||||
return k.subproject == our_project_id
|
||||
return True
|
||||
|
||||
if k.module == "python":
|
||||
if k.name == "install_env" and v.value == "prefix":
|
||||
@@ -519,10 +523,8 @@ def scrub_windows_devenv_dirs_from_path(raw_path: str, env: Mapping[str, str]) -
|
||||
return ";".join(clean_entries)
|
||||
|
||||
|
||||
def quote(path: str) -> str:
|
||||
if " " not in path:
|
||||
return path
|
||||
return "\"" + path.replace ("\"", "\\\"") + "\""
|
||||
def escape_depfile_path(path: str) -> str:
|
||||
return path.replace(" ", "\\ ")
|
||||
|
||||
|
||||
def query_releng_location(role: Role) -> Path:
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "frida-darwin.h"
|
||||
|
||||
gpointer
|
||||
_frida_dispatch_retain (gpointer object)
|
||||
{
|
||||
dispatch_retain (object);
|
||||
return object;
|
||||
}
|
||||
|
||||
void
|
||||
_frida_xpc_connection_set_event_handler (xpc_connection_t connection, FridaXpcHandler handler, gpointer user_data)
|
||||
{
|
||||
xpc_connection_set_event_handler (connection, ^(xpc_object_t object)
|
||||
{
|
||||
handler (object, user_data);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
_frida_xpc_connection_send_message_with_reply (xpc_connection_t connection, xpc_object_t message, dispatch_queue_t replyq,
|
||||
FridaXpcHandler handler, gpointer user_data, GDestroyNotify notify)
|
||||
{
|
||||
xpc_connection_send_message_with_reply (connection, message, replyq, ^(xpc_object_t object)
|
||||
{
|
||||
handler (object, user_data);
|
||||
if (notify != NULL)
|
||||
notify (user_data);
|
||||
});
|
||||
}
|
||||
|
||||
gchar *
|
||||
_frida_xpc_object_to_string (xpc_object_t object)
|
||||
{
|
||||
gchar * result;
|
||||
char * str;
|
||||
|
||||
str = xpc_copy_description (object);
|
||||
result = g_strdup (str);
|
||||
free (str);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_frida_xpc_dictionary_apply (xpc_object_t dict, FridaXpcDictionaryApplier applier, gpointer user_data)
|
||||
{
|
||||
return xpc_dictionary_apply (dict, ^bool (const char * key, xpc_object_t val)
|
||||
{
|
||||
return applier (key, val, user_data);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef __FRIDA_DARWIN_H__
|
||||
#define __FRIDA_DARWIN_H__
|
||||
|
||||
#ifdef HAVE_MACOS
|
||||
|
||||
#include <glib.h>
|
||||
#include <xpc/xpc.h>
|
||||
|
||||
typedef void (* FridaXpcHandler) (xpc_object_t object, gpointer user_data);
|
||||
typedef gboolean (* FridaXpcDictionaryApplier) (const gchar * key, xpc_object_t val, gpointer user_data);
|
||||
|
||||
gpointer _frida_dispatch_retain (gpointer object);
|
||||
|
||||
void _frida_xpc_connection_set_event_handler (xpc_connection_t connection, FridaXpcHandler handler, gpointer user_data);
|
||||
void _frida_xpc_connection_send_message_with_reply (xpc_connection_t connection, xpc_object_t message, dispatch_queue_t replyq,
|
||||
FridaXpcHandler handler, gpointer user_data, GDestroyNotify notify);
|
||||
gchar * _frida_xpc_object_to_string (xpc_object_t object);
|
||||
gboolean _frida_xpc_dictionary_apply (xpc_object_t dict, FridaXpcDictionaryApplier applier, gpointer user_data);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -9,9 +9,18 @@ base_sources = [
|
||||
'socket.vala',
|
||||
'socket-glue.c',
|
||||
'buffer.vala',
|
||||
'value.vala',
|
||||
]
|
||||
|
||||
extra_vala_args = []
|
||||
|
||||
if host_os == 'macos'
|
||||
base_sources += [
|
||||
'xpc.vala',
|
||||
'frida-darwin.c',
|
||||
]
|
||||
endif
|
||||
|
||||
extra_deps = []
|
||||
if host_os_family != 'windows'
|
||||
extra_vala_args += '--pkg=gio-unix-2.0'
|
||||
@@ -22,6 +31,12 @@ base_vala_args = [gum_vala_args, '--pkg=gio-2.0', '--pkg=json-glib-1.0']
|
||||
if nice_dep.found()
|
||||
base_vala_args += '--pkg=nice'
|
||||
endif
|
||||
if host_os_family == 'darwin'
|
||||
base_vala_args += [
|
||||
'--pkg=darwin-gcd',
|
||||
'--pkg=darwin-xpc',
|
||||
]
|
||||
endif
|
||||
|
||||
base = static_library('frida-base-' + api_version, base_sources,
|
||||
c_args: frida_component_cflags,
|
||||
|
||||
@@ -2079,6 +2079,17 @@ namespace Frida {
|
||||
}
|
||||
|
||||
namespace Numeric {
|
||||
public uint int64_hash (int64? val) {
|
||||
uint64 v = (uint64) val.abs ();
|
||||
return (uint) ((v >> 32) ^ (v & 0xffffffffU));
|
||||
}
|
||||
|
||||
public bool int64_equal (int64? val_a, int64? val_b) {
|
||||
int64 a = val_a;
|
||||
int64 b = val_b;
|
||||
return a == b;
|
||||
}
|
||||
|
||||
public uint uint64_hash (uint64? val) {
|
||||
uint64 v = val;
|
||||
return (uint) ((v >> 32) ^ (v & 0xffffffffU));
|
||||
|
||||
@@ -0,0 +1,392 @@
|
||||
namespace Frida {
|
||||
public interface ObjectBuilder : Object {
|
||||
public abstract unowned ObjectBuilder begin_dictionary ();
|
||||
public abstract unowned ObjectBuilder set_member_name (string name);
|
||||
public abstract unowned ObjectBuilder end_dictionary ();
|
||||
|
||||
public abstract unowned ObjectBuilder begin_array ();
|
||||
public abstract unowned ObjectBuilder end_array ();
|
||||
|
||||
public abstract unowned ObjectBuilder add_null_value ();
|
||||
public abstract unowned ObjectBuilder add_bool_value (bool val);
|
||||
public abstract unowned ObjectBuilder add_int64_value (int64 val);
|
||||
public abstract unowned ObjectBuilder add_uint64_value (uint64 val);
|
||||
public abstract unowned ObjectBuilder add_data_value (Bytes val);
|
||||
public abstract unowned ObjectBuilder add_string_value (string val);
|
||||
public abstract unowned ObjectBuilder add_uuid_value (string val);
|
||||
public abstract unowned ObjectBuilder add_raw_value (Bytes val);
|
||||
|
||||
public abstract Bytes build ();
|
||||
}
|
||||
|
||||
public interface ObjectReader : Object {
|
||||
public abstract bool has_member (string name) throws Error;
|
||||
public abstract unowned ObjectReader read_member (string name) throws Error;
|
||||
public abstract unowned ObjectReader end_member ();
|
||||
|
||||
public abstract uint count_elements () throws Error;
|
||||
public abstract unowned ObjectReader read_element (uint index) throws Error;
|
||||
public abstract unowned ObjectReader end_element () throws Error;
|
||||
|
||||
public abstract bool get_bool_value () throws Error;
|
||||
public abstract uint8 get_uint8_value () throws Error;
|
||||
public abstract uint16 get_uint16_value () throws Error;
|
||||
public abstract int64 get_int64_value () throws Error;
|
||||
public abstract uint64 get_uint64_value () throws Error;
|
||||
public abstract Bytes get_data_value () throws Error;
|
||||
public abstract unowned string get_string_value () throws Error;
|
||||
public abstract unowned string get_uuid_value () throws Error;
|
||||
}
|
||||
|
||||
public class VariantReader : Object, ObjectReader {
|
||||
public Variant root_object {
|
||||
get {
|
||||
return scopes.peek_head ().val;
|
||||
}
|
||||
}
|
||||
|
||||
public Variant current_object {
|
||||
get {
|
||||
return scopes.peek_tail ().val;
|
||||
}
|
||||
}
|
||||
|
||||
private Gee.Deque<Scope> scopes = new Gee.ArrayQueue<Scope> ();
|
||||
|
||||
public VariantReader (Variant v) {
|
||||
push_scope (v);
|
||||
}
|
||||
|
||||
public bool has_member (string name) throws Error {
|
||||
var scope = peek_scope ();
|
||||
if (scope.dict == null)
|
||||
throw new Error.PROTOCOL ("Dictionary expected, but at %s", scope.val.print (true));
|
||||
return scope.dict.contains (name);
|
||||
}
|
||||
|
||||
public unowned ObjectReader read_member (string name) throws Error {
|
||||
var scope = peek_scope ();
|
||||
if (scope.dict == null)
|
||||
throw new Error.PROTOCOL ("Dictionary expected, but at %s", scope.val.print (true));
|
||||
|
||||
Variant? v = scope.dict.lookup_value (name, null);
|
||||
if (v == null)
|
||||
throw new Error.PROTOCOL ("Key '%s' not found in dictionary: %s", name, scope.val.print (true));
|
||||
|
||||
push_scope (v);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectReader end_member () {
|
||||
pop_scope ();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public uint count_elements () throws Error {
|
||||
var scope = peek_scope ();
|
||||
scope.check_array ();
|
||||
return (uint) scope.val.n_children ();
|
||||
}
|
||||
|
||||
public unowned ObjectReader read_element (uint index) throws Error {
|
||||
var scope = peek_scope ();
|
||||
scope.check_array ();
|
||||
push_scope (scope.val.get_child_value (index).get_variant ());
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectReader end_element () throws Error {
|
||||
pop_scope ();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public bool get_bool_value () throws Error {
|
||||
return peek_scope ().get_value (VariantType.BOOLEAN).get_boolean ();
|
||||
}
|
||||
|
||||
public uint8 get_uint8_value () throws Error {
|
||||
return peek_scope ().get_value (VariantType.BYTE).get_byte ();
|
||||
}
|
||||
|
||||
public uint16 get_uint16_value () throws Error {
|
||||
return peek_scope ().get_value (VariantType.UINT16).get_uint16 ();
|
||||
}
|
||||
|
||||
public int64 get_int64_value () throws Error {
|
||||
return peek_scope ().get_value (VariantType.INT64).get_int64 ();
|
||||
}
|
||||
|
||||
public uint64 get_uint64_value () throws Error {
|
||||
return peek_scope ().get_value (VariantType.UINT64).get_uint64 ();
|
||||
}
|
||||
|
||||
public Bytes get_data_value () throws Error {
|
||||
return peek_scope ().get_value (new VariantType.array (VariantType.BYTE)).get_data_as_bytes ();
|
||||
}
|
||||
|
||||
public unowned string get_string_value () throws Error {
|
||||
return peek_scope ().get_value (VariantType.STRING).get_string ();
|
||||
}
|
||||
|
||||
public unowned string get_uuid_value () throws Error {
|
||||
return peek_scope ().get_value (VariantType.STRING).get_string (); // TODO: Use a tuple to avoid ambiguity.
|
||||
}
|
||||
|
||||
private void push_scope (Variant v) {
|
||||
scopes.offer_tail (new Scope (v));
|
||||
}
|
||||
|
||||
private Scope peek_scope () {
|
||||
return scopes.peek_tail ();
|
||||
}
|
||||
|
||||
private Scope pop_scope () {
|
||||
return scopes.poll_tail ();
|
||||
}
|
||||
|
||||
private class Scope {
|
||||
public Variant val;
|
||||
public VariantDict? dict;
|
||||
public bool is_array = false;
|
||||
|
||||
public Scope (Variant v) {
|
||||
val = v;
|
||||
|
||||
VariantType t = v.get_type ();
|
||||
if (t.equal (VariantType.VARDICT))
|
||||
dict = new VariantDict (v);
|
||||
else if (t.is_subtype_of (VariantType.ARRAY))
|
||||
is_array = true;
|
||||
}
|
||||
|
||||
public Variant get_value (VariantType expected_type) throws Error {
|
||||
if (!val.get_type ().equal (expected_type)) {
|
||||
throw new Error.PROTOCOL ("Expected type '%s', got '%s'",
|
||||
(string) expected_type.peek_string (),
|
||||
(string) val.get_type ().peek_string ());
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
public void check_array () throws Error {
|
||||
if (!is_array)
|
||||
throw new Error.PROTOCOL ("Array expected, but at %s", val.print (true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class JsonObjectBuilder : Object, ObjectBuilder {
|
||||
private Json.Builder builder = new Json.Builder ();
|
||||
private Gee.Map<string, Bytes> raw_values = new Gee.HashMap<string, Bytes> ();
|
||||
|
||||
public unowned ObjectBuilder begin_dictionary () {
|
||||
builder.begin_object ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectBuilder set_member_name (string name) {
|
||||
builder.set_member_name (name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectBuilder end_dictionary () {
|
||||
builder.end_object ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectBuilder begin_array () {
|
||||
builder.begin_array ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectBuilder end_array () {
|
||||
builder.end_array ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectBuilder add_null_value () {
|
||||
builder.add_null_value ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectBuilder add_bool_value (bool val) {
|
||||
builder.add_boolean_value (val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectBuilder add_int64_value (int64 val) {
|
||||
builder.add_int_value (val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectBuilder add_uint64_value (uint64 val) {
|
||||
builder.add_int_value ((int64) val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectBuilder add_data_value (Bytes val) {
|
||||
builder.add_string_value (Base64.encode (val.get_data ()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectBuilder add_string_value (string val) {
|
||||
builder.add_string_value (val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectBuilder add_uuid_value (string val) {
|
||||
builder.add_string_value (val);
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectBuilder add_raw_value (Bytes val) {
|
||||
string uuid = Uuid.string_random ();
|
||||
builder.add_string_value (uuid);
|
||||
raw_values[uuid] = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Bytes build () {
|
||||
string json = Json.to_string (builder.get_root (), false);
|
||||
|
||||
foreach (var e in raw_values.entries) {
|
||||
unowned string uuid = e.key;
|
||||
Bytes val = e.value;
|
||||
|
||||
unowned string raw_str = (string) val.get_data ();
|
||||
string str = raw_str[:(long) val.get_size ()];
|
||||
|
||||
json = json.replace ("\"" + uuid + "\"", str);
|
||||
}
|
||||
|
||||
return new Bytes (json.data);
|
||||
}
|
||||
}
|
||||
|
||||
public class JsonObjectReader : Object, ObjectReader {
|
||||
private Json.Reader reader;
|
||||
|
||||
public JsonObjectReader (string json) throws Error {
|
||||
try {
|
||||
reader = new Json.Reader (Json.from_string (json));
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.INVALID_ARGUMENT ("%s", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
public bool has_member (string name) throws Error {
|
||||
bool result = reader.read_member (name);
|
||||
reader.end_member ();
|
||||
return result;
|
||||
}
|
||||
|
||||
public unowned ObjectReader read_member (string name) throws Error {
|
||||
if (!reader.read_member (name))
|
||||
throw_dict_access_error ();
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectReader end_member () {
|
||||
reader.end_member ();
|
||||
return this;
|
||||
}
|
||||
|
||||
[NoReturn]
|
||||
private void throw_dict_access_error () throws Error {
|
||||
GLib.Error e = reader.get_error ();
|
||||
reader.end_member ();
|
||||
throw new Error.PROTOCOL ("%s", e.message);
|
||||
}
|
||||
|
||||
public uint count_elements () throws Error {
|
||||
int n = reader.count_elements ();
|
||||
if (n == -1)
|
||||
throw_array_access_error ();
|
||||
return n;
|
||||
}
|
||||
|
||||
public unowned ObjectReader read_element (uint index) throws Error {
|
||||
if (!reader.read_element (index)) {
|
||||
GLib.Error e = reader.get_error ();
|
||||
reader.end_element ();
|
||||
throw new Error.PROTOCOL ("%s", e.message);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned ObjectReader end_element () throws Error {
|
||||
reader.end_element ();
|
||||
return this;
|
||||
}
|
||||
|
||||
[NoReturn]
|
||||
private void throw_array_access_error () throws Error {
|
||||
GLib.Error e = reader.get_error ();
|
||||
reader.end_element ();
|
||||
throw new Error.PROTOCOL ("%s", e.message);
|
||||
}
|
||||
|
||||
public bool get_bool_value () throws Error {
|
||||
bool v = reader.get_boolean_value ();
|
||||
if (!v)
|
||||
maybe_throw_value_access_error ();
|
||||
return v;
|
||||
}
|
||||
|
||||
public uint8 get_uint8_value () throws Error {
|
||||
int64 v = get_int64_value ();
|
||||
if (v < 0 || v > uint8.MAX)
|
||||
throw new Error.PROTOCOL ("Invalid uint8");
|
||||
return (uint8) v;
|
||||
}
|
||||
|
||||
public uint16 get_uint16_value () throws Error {
|
||||
int64 v = get_int64_value ();
|
||||
if (v < 0 || v > uint16.MAX)
|
||||
throw new Error.PROTOCOL ("Invalid uint16");
|
||||
return (uint16) v;
|
||||
}
|
||||
|
||||
public int64 get_int64_value () throws Error {
|
||||
int64 v = reader.get_int_value ();
|
||||
if (v == 0)
|
||||
maybe_throw_value_access_error ();
|
||||
return v;
|
||||
}
|
||||
|
||||
public uint64 get_uint64_value () throws Error {
|
||||
int64 v = get_int64_value ();
|
||||
if (v < 0)
|
||||
throw new Error.PROTOCOL ("Invalid uint64");
|
||||
return v;
|
||||
}
|
||||
|
||||
public Bytes get_data_value () throws Error {
|
||||
return new Bytes (Base64.decode (get_string_value ()));
|
||||
}
|
||||
|
||||
public unowned string get_string_value () throws Error {
|
||||
unowned string? v = reader.get_string_value ();
|
||||
if (v == null)
|
||||
maybe_throw_value_access_error ();
|
||||
return v;
|
||||
}
|
||||
|
||||
public unowned string get_uuid_value () throws Error {
|
||||
return get_string_value ();
|
||||
}
|
||||
|
||||
private void maybe_throw_value_access_error () throws Error {
|
||||
GLib.Error? e = reader.get_error ();
|
||||
if (e == null)
|
||||
return;
|
||||
reader.end_member ();
|
||||
throw new Error.PROTOCOL ("%s", e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
namespace Frida {
|
||||
public class XpcClient : Object {
|
||||
public signal void message (Darwin.Xpc.Object obj);
|
||||
|
||||
public State state {
|
||||
get {
|
||||
return _state;
|
||||
}
|
||||
}
|
||||
|
||||
public Darwin.Xpc.Connection connection {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
public Darwin.GCD.DispatchQueue queue {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
private State _state;
|
||||
private string? close_reason;
|
||||
private MainContext main_context;
|
||||
|
||||
public enum State {
|
||||
OPEN,
|
||||
CLOSING,
|
||||
CLOSED,
|
||||
}
|
||||
|
||||
public static XpcClient make_for_mach_service (string name, Darwin.GCD.DispatchQueue queue) {
|
||||
return new XpcClient (Darwin.Xpc.Connection.create_mach_service (name, queue, 0), queue);
|
||||
}
|
||||
|
||||
public XpcClient (Darwin.Xpc.Connection connection, Darwin.GCD.DispatchQueue queue) {
|
||||
Object (connection: connection, queue: queue);
|
||||
}
|
||||
|
||||
construct {
|
||||
main_context = MainContext.ref_thread_default ();
|
||||
|
||||
connection.set_event_handler (on_event);
|
||||
connection.activate ();
|
||||
}
|
||||
|
||||
public override void dispose () {
|
||||
if (close_reason != null) {
|
||||
change_state (CLOSED);
|
||||
} else {
|
||||
change_state (CLOSING);
|
||||
this.ref ();
|
||||
connection.cancel ();
|
||||
}
|
||||
|
||||
base.dispose ();
|
||||
}
|
||||
|
||||
public async Darwin.Xpc.Object request (Darwin.Xpc.Object message, Cancellable? cancellable) throws Error, IOError {
|
||||
Darwin.Xpc.Object? reply = null;
|
||||
connection.send_message_with_reply (message, queue, r => {
|
||||
schedule_on_frida_thread (() => {
|
||||
reply = r;
|
||||
request.callback ();
|
||||
return Source.REMOVE;
|
||||
});
|
||||
});
|
||||
|
||||
yield;
|
||||
|
||||
if (reply.type == Darwin.Xpc.Error.TYPE) {
|
||||
var e = (Darwin.Xpc.Error) reply;
|
||||
throw new Error.NOT_SUPPORTED ("%s", e.get_string (Darwin.Xpc.Error.KEY_DESCRIPTION));
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
private void change_state (State new_state) {
|
||||
_state = new_state;
|
||||
notify_property ("state");
|
||||
}
|
||||
|
||||
private void on_event (Darwin.Xpc.Object obj) {
|
||||
schedule_on_frida_thread (() => {
|
||||
if (obj.type == Darwin.Xpc.Error.TYPE) {
|
||||
var e = (Darwin.Xpc.Error) obj;
|
||||
close_reason = e.get_string (Darwin.Xpc.Error.KEY_DESCRIPTION);
|
||||
if (state == CLOSING) {
|
||||
change_state (CLOSED);
|
||||
unref ();
|
||||
}
|
||||
} else {
|
||||
message (obj);
|
||||
}
|
||||
return Source.REMOVE;
|
||||
});
|
||||
}
|
||||
|
||||
private void schedule_on_frida_thread (owned SourceFunc function) {
|
||||
var source = new IdleSource ();
|
||||
source.set_callback ((owned) function);
|
||||
source.attach (main_context);
|
||||
}
|
||||
}
|
||||
|
||||
public class XpcObjectReader {
|
||||
public Darwin.Xpc.Object root_object {
|
||||
get {
|
||||
return scopes.peek_head ().object;
|
||||
}
|
||||
}
|
||||
|
||||
public Darwin.Xpc.Object current_object {
|
||||
get {
|
||||
return scopes.peek_tail ().object;
|
||||
}
|
||||
}
|
||||
|
||||
private Gee.Deque<Scope> scopes = new Gee.ArrayQueue<Scope> ();
|
||||
|
||||
public XpcObjectReader (Darwin.Xpc.Object obj) {
|
||||
push_scope (obj);
|
||||
}
|
||||
|
||||
public bool has_member (string name) throws Error {
|
||||
return peek_scope ().get_dictionary ().get_value (name) != null;
|
||||
}
|
||||
|
||||
public bool try_read_member (string name) throws Error {
|
||||
var scope = peek_scope ();
|
||||
var dict = scope.get_dictionary ();
|
||||
var val = dict.get_value (name);
|
||||
if (val == null)
|
||||
return false;
|
||||
|
||||
push_scope (val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public unowned XpcObjectReader read_member (string name) throws Error {
|
||||
var scope = peek_scope ();
|
||||
var dict = scope.get_dictionary ();
|
||||
var val = dict.get_value (name);
|
||||
if (val == null)
|
||||
throw new Error.PROTOCOL ("Key '%s' not found in dictionary: %s", name, scope.object.to_string ());
|
||||
|
||||
push_scope (val);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned XpcObjectReader end_member () {
|
||||
pop_scope ();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public size_t count_elements () throws Error {
|
||||
return peek_scope ().get_array ().count;
|
||||
}
|
||||
|
||||
public unowned XpcObjectReader read_element (size_t index) throws Error {
|
||||
push_scope (peek_scope ().get_array ().get_value (index));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public unowned XpcObjectReader end_element () throws Error {
|
||||
pop_scope ();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public bool get_bool_value () throws Error {
|
||||
return peek_scope ().get_object<Darwin.Xpc.Bool> (Darwin.Xpc.Bool.TYPE).get_value ();
|
||||
}
|
||||
|
||||
public int64 get_int64_value () throws Error {
|
||||
return peek_scope ().get_object<Darwin.Xpc.Int64> (Darwin.Xpc.Int64.TYPE).get_value ();
|
||||
}
|
||||
|
||||
public uint64 get_uint64_value () throws Error {
|
||||
return peek_scope ().get_object<Darwin.Xpc.UInt64> (Darwin.Xpc.UInt64.TYPE).get_value ();
|
||||
}
|
||||
|
||||
public unowned string get_string_value () throws Error {
|
||||
return peek_scope ().get_object<Darwin.Xpc.String> (Darwin.Xpc.String.TYPE).get_string_ptr ();
|
||||
}
|
||||
|
||||
public unowned string get_error_description () throws Error {
|
||||
var error = peek_scope ().get_object<Darwin.Xpc.Error> (Darwin.Xpc.Error.TYPE);
|
||||
return error.get_string (Darwin.Xpc.Error.KEY_DESCRIPTION);
|
||||
}
|
||||
|
||||
public unowned Darwin.Xpc.Object get_object_value (Darwin.Xpc.Type expected_type) throws Error {
|
||||
return peek_scope ().get_object<Darwin.Xpc.Object> (expected_type);
|
||||
}
|
||||
|
||||
private void push_scope (Darwin.Xpc.Object obj) {
|
||||
scopes.offer_tail (new Scope (obj));
|
||||
}
|
||||
|
||||
private Scope peek_scope () {
|
||||
return scopes.peek_tail ();
|
||||
}
|
||||
|
||||
private Scope pop_scope () {
|
||||
return scopes.poll_tail ();
|
||||
}
|
||||
|
||||
private class Scope {
|
||||
public Darwin.Xpc.Object object;
|
||||
private unowned Darwin.Xpc.Type type;
|
||||
|
||||
public Scope (Darwin.Xpc.Object obj) {
|
||||
object = obj;
|
||||
type = obj.type;
|
||||
}
|
||||
|
||||
public unowned T get_object<T> (Darwin.Xpc.Type expected_type) throws Error {
|
||||
if (type != expected_type)
|
||||
throw new Error.PROTOCOL ("Expected type '%s', got '%s'", expected_type.name, type.name);
|
||||
return object;
|
||||
}
|
||||
|
||||
public unowned Darwin.Xpc.Array get_array () throws Error {
|
||||
return get_object<Darwin.Xpc.Array> (Darwin.Xpc.Array.TYPE);
|
||||
}
|
||||
|
||||
public unowned Darwin.Xpc.Dictionary get_dictionary () throws Error {
|
||||
return get_object<Darwin.Xpc.Dictionary> (Darwin.Xpc.Dictionary.TYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
-5
@@ -413,7 +413,7 @@ else
|
||||
endif
|
||||
uninstalled_girdir = meson.current_build_dir() / 'src'
|
||||
|
||||
vapidir = get_option('datadir') / 'vala' / 'vapi'
|
||||
vapidir = get_option('prefix') / get_option('datadir') / 'vala' / 'vapi'
|
||||
|
||||
gum_vala_args = [
|
||||
'--pkg=frida-gum-1.0',
|
||||
@@ -437,6 +437,25 @@ backend_deps_private = []
|
||||
backend_reqs_private = []
|
||||
backend_libs_private = []
|
||||
|
||||
openssl_options = [
|
||||
'cli=disabled',
|
||||
]
|
||||
if host_os_family == 'windows' and cc.get_argument_syntax() != 'msvc'
|
||||
openssl_options += 'asm=disabled'
|
||||
endif
|
||||
openssl_dep = dependency('openssl',
|
||||
required: have_fruity_backend or get_option('connectivity').enabled(),
|
||||
modules: cc.get_argument_syntax() == 'msvc' ? ['OpenSSL::SSL'] : [],
|
||||
default_options: openssl_options,
|
||||
)
|
||||
|
||||
if have_fruity_backend
|
||||
foreach dep : ['libnghttp2', 'libngtcp2', 'libngtcp2_crypto_quictls', 'lwip']
|
||||
backend_deps_private += dependency(dep)
|
||||
backend_reqs_private += dep
|
||||
endforeach
|
||||
endif
|
||||
|
||||
if quickjs_dep.found()
|
||||
backend_deps_private += quickjs_dep
|
||||
backend_reqs_private += 'quickjs'
|
||||
@@ -456,8 +475,19 @@ else
|
||||
termux_elf_cleaner = []
|
||||
endif
|
||||
|
||||
tls_provider_dep = dependency('gioopenssl', required: get_option('connectivity'))
|
||||
tls_provider_dep = dependency('gioopenssl', required: get_option('connectivity'), default_options: [
|
||||
'gnutls=disabled',
|
||||
'openssl=enabled',
|
||||
'libproxy=disabled',
|
||||
'gnome_proxy=disabled',
|
||||
'tests=false',
|
||||
])
|
||||
tls_provider_vala_args = []
|
||||
if tls_provider_dep.found()
|
||||
tls_provider_vala_args += [
|
||||
'--pkg=gioopenssl',
|
||||
'--vapidir=' + tls_provider_dep.get_variable('vapidir'),
|
||||
]
|
||||
cdata.set('HAVE_GIOOPENSSL', 1)
|
||||
vala_flags += ['--define=HAVE_GIOOPENSSL']
|
||||
backend_deps_private += tls_provider_dep
|
||||
@@ -473,7 +503,6 @@ nice_dep = dependency('nice', required: get_option('connectivity'), default_opti
|
||||
'introspection=disabled',
|
||||
])
|
||||
if nice_dep.found()
|
||||
openssl_dep = dependency('openssl')
|
||||
usrsctp_dep = dependency('usrsctp', default_options: [
|
||||
'sctp_inet=false',
|
||||
'sctp_inet6=false',
|
||||
@@ -489,7 +518,6 @@ if nice_dep.found()
|
||||
cdata.set('HAVE_SCONN_LEN', 1)
|
||||
endif
|
||||
else
|
||||
openssl_dep = []
|
||||
usrsctp_dep = []
|
||||
endif
|
||||
|
||||
@@ -500,7 +528,7 @@ if host_os_family == 'darwin'
|
||||
backend_libs_private += ['-Wl,-framework,Foundation', '-lbsm']
|
||||
endif
|
||||
if host_os == 'macos'
|
||||
backend_libs_private += ['-Wl,-framework,AppKit']
|
||||
backend_libs_private += ['-Wl,-framework,AppKit', '-Wl,-framework,IOKit']
|
||||
endif
|
||||
if host_os in ['ios', 'tvos']
|
||||
backend_libs_private += ['-Wl,-framework,CoreGraphics', '-Wl,-framework,UIKit']
|
||||
|
||||
+1
-11
@@ -101,16 +101,6 @@ option('agent_emulated_legacy',
|
||||
description: 'Prebuilt agent to embed for use on legacy emulated targets'
|
||||
)
|
||||
|
||||
option('agent_dbghelp_prefix',
|
||||
type: 'string',
|
||||
description: 'Location of DbgHelp binaries to embed alongside agent (Windows only)'
|
||||
)
|
||||
|
||||
option('agent_symsrv_prefix',
|
||||
type: 'string',
|
||||
description: 'Location of SymSrv binaries to embed alongside agent (Windows only)'
|
||||
)
|
||||
|
||||
option('gadget',
|
||||
type: 'feature',
|
||||
value: 'auto',
|
||||
@@ -137,7 +127,7 @@ option('inject',
|
||||
|
||||
option('connectivity',
|
||||
type: 'feature',
|
||||
value: 'auto',
|
||||
value: 'enabled',
|
||||
description: 'Internet connectivity features (TLS and ICE support)'
|
||||
)
|
||||
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ if tls_provider_dep.found()
|
||||
endif
|
||||
|
||||
raw_portal = executable('frida-portal-raw', portal_sources,
|
||||
vala_args: [core_vala_args, '--pkg=posix'],
|
||||
vala_args: [core_vala_args, tls_provider_vala_args, '--pkg=posix'],
|
||||
link_args: extra_link_args,
|
||||
link_depends: extra_link_depends,
|
||||
dependencies: [core_dep] + extra_deps,
|
||||
|
||||
+1
-1
Submodule releng updated: 56b262207c...b0e46f7b69.
+15
-15
@@ -90,17 +90,25 @@ else
|
||||
endif
|
||||
uninstalled_vapidir = uninstalled_incdir
|
||||
|
||||
uninstalled_variables = {
|
||||
'frida_includedir': uninstalled_incdir,
|
||||
'frida_girdir': uninstalled_girdir,
|
||||
'frida_vapidir': uninstalled_vapidir,
|
||||
}
|
||||
|
||||
installed_variables = {
|
||||
'frida_includedir': '${includedir}',
|
||||
'frida_girdir': girdir,
|
||||
'frida_vapidir': vapidir,
|
||||
}
|
||||
|
||||
core_public_dep = declare_dependency(
|
||||
sources: [core_public_h, core_public_gir, core_public_vapi_stamp, core_public_extra_headers],
|
||||
include_directories: include_directories('.'),
|
||||
link_args: backend_libs_private,
|
||||
link_with: core_public_lib,
|
||||
dependencies: core_deps,
|
||||
variables: {
|
||||
'frida_includedir': uninstalled_incdir,
|
||||
'frida_girdir': uninstalled_girdir,
|
||||
'frida_vapidir': uninstalled_vapidir,
|
||||
},
|
||||
variables: uninstalled_variables,
|
||||
)
|
||||
|
||||
pkg = import('pkgconfig')
|
||||
@@ -115,16 +123,8 @@ pkg.generate(
|
||||
libraries: core_public_lib,
|
||||
libraries_private: backend_libs_private,
|
||||
extra_cflags: ['-I${frida_includedir}'],
|
||||
variables: {
|
||||
'frida_includedir': '${includedir}',
|
||||
'frida_girdir': girdir,
|
||||
'frida_vapidir': vapidir,
|
||||
},
|
||||
uninstalled_variables: {
|
||||
'frida_includedir': uninstalled_incdir,
|
||||
'frida_girdir': uninstalled_girdir,
|
||||
'frida_vapidir': uninstalled_vapidir,
|
||||
},
|
||||
variables: installed_variables,
|
||||
uninstalled_variables: uninstalled_variables,
|
||||
)
|
||||
|
||||
meson.override_dependency(f'frida-core-@api_version@', core_public_dep)
|
||||
@@ -428,6 +428,8 @@ static void frida_agent_context_emit_mach_stub_code (FridaAgentContext * self, g
|
||||
static void frida_agent_context_emit_pthread_stub_code (FridaAgentContext * self, guint8 * code, GumDarwinModuleResolver * resolver,
|
||||
GumDarwinMapper * mapper);
|
||||
|
||||
static gboolean frida_convert_thread_state_for_task (mach_port_t task, thread_state_flavor_t flavor, gconstpointer in_state,
|
||||
mach_msg_type_number_t in_state_count, gpointer out_state, mach_msg_type_number_t * out_state_count, GError ** error);
|
||||
static mach_port_t frida_obtain_thread_port_for_thread_id (mach_port_t task, uint64_t thread_id);
|
||||
static kern_return_t frida_get_thread_state (mach_port_t thread, thread_state_flavor_t flavor, gpointer state,
|
||||
mach_msg_type_number_t * count);
|
||||
@@ -2583,16 +2585,24 @@ static gboolean
|
||||
frida_inject_instance_start_thread (FridaInjectInstance * self, GError ** error)
|
||||
{
|
||||
gboolean success = FALSE;
|
||||
thread_state_t thread_state;
|
||||
mach_msg_type_number_t thread_state_count;
|
||||
kern_return_t kr;
|
||||
const gchar * failed_operation;
|
||||
FridaHelperContext * ctx = self->backend->context;
|
||||
dispatch_source_t source;
|
||||
|
||||
kr = thread_create (self->task, &self->thread);
|
||||
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "thread_create");
|
||||
thread_state = g_alloca (self->thread_state_count * sizeof (natural_t));
|
||||
thread_state_count = self->thread_state_count;
|
||||
|
||||
kr = frida_set_thread_state (self->thread, self->thread_state_flavor, self->thread_state_data, self->thread_state_count);
|
||||
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "set_thread_state");
|
||||
if (!frida_convert_thread_state_for_task (self->task, self->thread_state_flavor, self->thread_state_data, self->thread_state_count,
|
||||
thread_state, &thread_state_count, error))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
kr = thread_create_running (self->task, self->thread_state_flavor, thread_state, thread_state_count, &self->thread);
|
||||
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "thread_create");
|
||||
|
||||
source = dispatch_source_create (DISPATCH_SOURCE_TYPE_MACH_SEND, self->thread, DISPATCH_MACH_SEND_DEAD, ctx->dispatch_queue);
|
||||
self->thread_monitor_source = source;
|
||||
@@ -2601,9 +2611,6 @@ frida_inject_instance_start_thread (FridaInjectInstance * self, GError ** error)
|
||||
dispatch_source_set_event_handler_f (source, frida_inject_instance_on_mach_thread_dead);
|
||||
dispatch_resume (source);
|
||||
|
||||
kr = thread_resume (self->thread);
|
||||
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "thread_resume");
|
||||
|
||||
success = TRUE;
|
||||
|
||||
goto beach;
|
||||
@@ -5072,6 +5079,52 @@ frida_agent_context_emit_arm64_pthread_stub_body (FridaAgentContext * self, Frid
|
||||
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
frida_convert_thread_state_for_task (mach_port_t task, thread_state_flavor_t flavor, gconstpointer in_state,
|
||||
mach_msg_type_number_t in_state_count, gpointer out_state, mach_msg_type_number_t * out_state_count,
|
||||
GError ** error)
|
||||
{
|
||||
gboolean success = FALSE;
|
||||
kern_return_t kr;
|
||||
const gchar * failed_operation;
|
||||
thread_act_array_t threads = NULL;
|
||||
mach_msg_type_number_t thread_count = 0;
|
||||
|
||||
kr = task_threads (task, &threads, &thread_count);
|
||||
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "task_threads");
|
||||
|
||||
kr = frida_convert_thread_state (threads[0], FRIDA_CONVERT_THREAD_STATE_OUT, flavor, in_state, in_state_count,
|
||||
out_state, out_state_count);
|
||||
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "thread_convert_thread_state");
|
||||
|
||||
success = TRUE;
|
||||
|
||||
goto beach;
|
||||
|
||||
mach_failure:
|
||||
{
|
||||
g_set_error (error,
|
||||
FRIDA_ERROR,
|
||||
FRIDA_ERROR_NOT_SUPPORTED,
|
||||
"Unexpected error while converting thread state for task (%s returned '%s')",
|
||||
failed_operation, mach_error_string (kr));
|
||||
goto beach;
|
||||
}
|
||||
beach:
|
||||
{
|
||||
mach_msg_type_number_t i;
|
||||
|
||||
if (threads != NULL)
|
||||
{
|
||||
for (i = 0; i != thread_count; i++)
|
||||
mach_port_deallocate (mach_task_self (), threads[i]);
|
||||
vm_deallocate (mach_task_self (), (vm_address_t) threads, thread_count * sizeof (thread_t));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
static mach_port_t
|
||||
frida_obtain_thread_port_for_thread_id (mach_port_t task, uint64_t thread_id)
|
||||
{
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public class DroidyHostSessionProvider : Object, HostSessionProvider, ChannelProvider {
|
||||
public class DroidyHostSessionProvider : Object, HostSessionProvider, HostChannelProvider {
|
||||
public string id {
|
||||
get { return device_details.serial; }
|
||||
}
|
||||
@@ -162,7 +162,7 @@ namespace Frida {
|
||||
agent_session_detached (id, reason, crash);
|
||||
}
|
||||
|
||||
public async IOStream open_channel (string address, Cancellable? cancellable = null) throws Error, IOError {
|
||||
public async IOStream open_channel (string address, Cancellable? cancellable) throws Error, IOError {
|
||||
if (address.contains (":")) {
|
||||
Droidy.Client client = null;
|
||||
try {
|
||||
@@ -188,7 +188,7 @@ namespace Frida {
|
||||
construct;
|
||||
}
|
||||
|
||||
public weak ChannelProvider channel_provider {
|
||||
public weak HostChannelProvider channel_provider {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
@@ -216,7 +216,7 @@ namespace Frida {
|
||||
private const double MIN_SERVER_CHECK_INTERVAL = 5.0;
|
||||
private const string GADGET_APP_ID = "re.frida.Gadget";
|
||||
|
||||
public DroidyHostSession (Droidy.DeviceDetails device_details, ChannelProvider channel_provider) {
|
||||
public DroidyHostSession (Droidy.DeviceDetails device_details, HostChannelProvider channel_provider) {
|
||||
Object (
|
||||
device_details: device_details,
|
||||
channel_provider: channel_provider
|
||||
|
||||
+2
-2
@@ -37,12 +37,12 @@ def main(argv):
|
||||
shutil.copy(agent, embedded_agent)
|
||||
|
||||
if agent_dbghelp_prefix is not None:
|
||||
shutil.copy(agent_dbghelp_prefix / f"dbghelp-{flavor}.dll", embedded_dbghelp)
|
||||
shutil.copy(agent_dbghelp_prefix / flavor / "dbghelp.dll", embedded_dbghelp)
|
||||
else:
|
||||
embedded_dbghelp.write_bytes(b"")
|
||||
|
||||
if agent_symsrv_prefix is not None:
|
||||
shutil.copy(agent_symsrv_prefix / f"symsrv-{flavor}.dll", embedded_symsrv)
|
||||
shutil.copy(agent_symsrv_prefix / flavor / "symsrv.dll", embedded_symsrv)
|
||||
else:
|
||||
embedded_symsrv.write_bytes(b"")
|
||||
else:
|
||||
|
||||
+100
-1
@@ -530,6 +530,7 @@ namespace Frida {
|
||||
private Gee.HashSet<Promise<Session>> pending_attach_requests = new Gee.HashSet<Promise<Session>> ();
|
||||
private Gee.HashMap<AgentSessionId?, Promise<bool>> pending_detach_requests =
|
||||
new Gee.HashMap<AgentSessionId?, Promise<bool>> (AgentSessionId.hash, AgentSessionId.equal);
|
||||
private Gee.Set<Service> services = new Gee.HashSet<Service> ();
|
||||
private Bus _bus;
|
||||
|
||||
internal Device (DeviceManager? manager, string id, string name, HostSessionProviderKind kind, HostSessionProvider provider,
|
||||
@@ -1228,7 +1229,7 @@ namespace Frida {
|
||||
public async IOStream open_channel (string address, Cancellable? cancellable = null) throws Error, IOError {
|
||||
check_open ();
|
||||
|
||||
var channel_provider = provider as ChannelProvider;
|
||||
var channel_provider = provider as HostChannelProvider;
|
||||
if (channel_provider == null)
|
||||
throw new Error.NOT_SUPPORTED ("Channels are not supported by this device");
|
||||
|
||||
@@ -1249,6 +1250,38 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public async Service open_service (string address, Cancellable? cancellable = null) throws Error, IOError {
|
||||
check_open ();
|
||||
|
||||
var service_provider = provider as HostServiceProvider;
|
||||
if (service_provider == null)
|
||||
throw new Error.NOT_SUPPORTED ("Services are not supported by this device");
|
||||
|
||||
var service = yield service_provider.open_service (address, cancellable);
|
||||
service.close.connect (on_service_closed);
|
||||
services.add (service);
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
public Service open_service_sync (string address, Cancellable? cancellable = null) throws Error, IOError {
|
||||
var task = create<OpenServiceTask> ();
|
||||
task.address = address;
|
||||
return task.execute (cancellable);
|
||||
}
|
||||
|
||||
private class OpenServiceTask : DeviceTask<Service> {
|
||||
public string address;
|
||||
|
||||
protected override async Service perform_operation () throws Error, IOError {
|
||||
return yield parent.open_service (address, cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
private void on_service_closed (Service service) {
|
||||
services.remove (service);
|
||||
}
|
||||
|
||||
public async void unpair (Cancellable? cancellable = null) throws Error, IOError {
|
||||
check_open ();
|
||||
|
||||
@@ -1357,6 +1390,10 @@ namespace Frida {
|
||||
close_request = new Promise<bool> ();
|
||||
|
||||
try {
|
||||
foreach (var service in services.to_array ())
|
||||
yield service.cancel (cancellable);
|
||||
services.clear ();
|
||||
|
||||
while (!pending_detach_requests.is_empty) {
|
||||
var iterator = pending_detach_requests.entries.iterator ();
|
||||
iterator.next ();
|
||||
@@ -1964,6 +2001,68 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public interface Service : Object {
|
||||
public signal void close ();
|
||||
public signal void message (Variant message);
|
||||
|
||||
public abstract bool is_closed ();
|
||||
|
||||
public abstract async void activate (Cancellable? cancellable = null) throws Error, IOError;
|
||||
|
||||
public void activate_sync (Cancellable? cancellable = null) throws Error, IOError {
|
||||
create<ActivateTask> ().execute (cancellable);
|
||||
}
|
||||
|
||||
private class ActivateTask : ServiceTask<void> {
|
||||
protected override async void perform_operation () throws Error, IOError {
|
||||
yield parent.activate (cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract async void cancel (Cancellable? cancellable = null) throws IOError;
|
||||
|
||||
public void cancel_sync (Cancellable? cancellable = null) throws IOError {
|
||||
try {
|
||||
create<CancelTask> ().execute (cancellable);
|
||||
} catch (Error e) {
|
||||
assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
private class CancelTask : ServiceTask<void> {
|
||||
protected override async void perform_operation () throws IOError {
|
||||
yield parent.cancel (cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract async Variant request (Variant parameters, Cancellable? cancellable = null) throws Error, IOError;
|
||||
|
||||
public Variant request_sync (Variant parameters, Cancellable? cancellable = null) throws Error, IOError {
|
||||
var task = create<RequestTask> () as RequestTask;
|
||||
task.parameters = parameters;
|
||||
return task.execute (cancellable);
|
||||
}
|
||||
|
||||
private class RequestTask : ServiceTask<Variant> {
|
||||
public Variant parameters;
|
||||
|
||||
protected override async Variant perform_operation () throws Error, IOError {
|
||||
return yield parent.request (parameters, cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
private T create<T> () {
|
||||
return Object.new (typeof (T), parent: this);
|
||||
}
|
||||
|
||||
private abstract class ServiceTask<T> : AsyncTask<T> {
|
||||
public weak Service parent {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Session : Object, AgentMessageSink {
|
||||
public signal void detached (SessionDetachReason reason, Crash? crash);
|
||||
|
||||
|
||||
+152
-150
@@ -1,18 +1,18 @@
|
||||
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
|
||||
namespace Frida.Fruity {
|
||||
public class DeviceInfoService : Object, AsyncInitable {
|
||||
public ChannelProvider channel_provider {
|
||||
public HostChannelProvider channel_provider {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
private DTXChannel channel;
|
||||
|
||||
private DeviceInfoService (ChannelProvider channel_provider) {
|
||||
private DeviceInfoService (HostChannelProvider channel_provider) {
|
||||
Object (channel_provider: channel_provider);
|
||||
}
|
||||
|
||||
public static async DeviceInfoService open (ChannelProvider channel_provider, Cancellable? cancellable = null)
|
||||
public static async DeviceInfoService open (HostChannelProvider channel_provider, Cancellable? cancellable = null)
|
||||
throws Error, IOError {
|
||||
var service = new DeviceInfoService (channel_provider);
|
||||
|
||||
@@ -74,21 +74,53 @@ namespace Frida.Fruity {
|
||||
return "/private" + name;
|
||||
return name;
|
||||
}
|
||||
|
||||
public class ProcessInfo : Object {
|
||||
public uint pid {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string name {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string real_app_name {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool is_application {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool foreground_running {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public DateTime? start_date {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ApplicationListingService : Object, AsyncInitable {
|
||||
public ChannelProvider channel_provider {
|
||||
public HostChannelProvider channel_provider {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
private DTXChannel channel;
|
||||
|
||||
private ApplicationListingService (ChannelProvider channel_provider) {
|
||||
private ApplicationListingService (HostChannelProvider channel_provider) {
|
||||
Object (channel_provider: channel_provider);
|
||||
}
|
||||
|
||||
public static async ApplicationListingService open (ChannelProvider channel_provider, Cancellable? cancellable = null)
|
||||
public static async ApplicationListingService open (HostChannelProvider channel_provider, Cancellable? cancellable = null)
|
||||
throws Error, IOError {
|
||||
var service = new ApplicationListingService (channel_provider);
|
||||
|
||||
@@ -178,21 +210,115 @@ namespace Frida.Fruity {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public class ApplicationInfo : Object {
|
||||
public ApplicationType app_type {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string display_name {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string bundle_identifier {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string bundle_path {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string? version {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool placeholder {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool restricted {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string? executable_name {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string[]? app_extension_uuids {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string? plugin_uuid {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string? plugin_identifier {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string? container_bundle_identifier {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string? container_bundle_path {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ApplicationType {
|
||||
SYSTEM = 1,
|
||||
USER,
|
||||
PLUGIN_KIT;
|
||||
|
||||
public static ApplicationType from_nick (string nick) throws Error {
|
||||
return Marshal.enum_from_nick<ApplicationType> (nick);
|
||||
}
|
||||
|
||||
public string to_nick () {
|
||||
return Marshal.enum_to_nick<ApplicationType> (this);
|
||||
}
|
||||
|
||||
internal static ApplicationType from_dtx (string type) {
|
||||
if (type == "System")
|
||||
return SYSTEM;
|
||||
|
||||
if (type == "User")
|
||||
return USER;
|
||||
|
||||
if (type == "PluginKit")
|
||||
return PLUGIN_KIT;
|
||||
|
||||
assert_not_reached ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ProcessControlService : Object, AsyncInitable {
|
||||
public ChannelProvider channel_provider {
|
||||
public HostChannelProvider channel_provider {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
private DTXChannel channel;
|
||||
|
||||
private ProcessControlService (ChannelProvider channel_provider) {
|
||||
private ProcessControlService (HostChannelProvider channel_provider) {
|
||||
Object (channel_provider: channel_provider);
|
||||
}
|
||||
|
||||
public static async ProcessControlService open (ChannelProvider channel_provider, Cancellable? cancellable = null)
|
||||
public static async ProcessControlService open (HostChannelProvider channel_provider, Cancellable? cancellable = null)
|
||||
throws Error, IOError {
|
||||
var service = new ProcessControlService (channel_provider);
|
||||
|
||||
@@ -220,132 +346,6 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class ProcessInfo : Object {
|
||||
public uint pid {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string name {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string real_app_name {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool is_application {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool foreground_running {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public DateTime? start_date {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
public class ApplicationInfo : Object {
|
||||
public ApplicationType app_type {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string display_name {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string bundle_identifier {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string bundle_path {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string? version {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool placeholder {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool restricted {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string? executable_name {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string[]? app_extension_uuids {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string? plugin_uuid {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string? plugin_identifier {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string? container_bundle_identifier {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string? container_bundle_path {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ApplicationType {
|
||||
SYSTEM = 1,
|
||||
USER,
|
||||
PLUGIN_KIT;
|
||||
|
||||
public static ApplicationType from_nick (string nick) throws Error {
|
||||
return Marshal.enum_from_nick<ApplicationType> (nick);
|
||||
}
|
||||
|
||||
public string to_nick () {
|
||||
return Marshal.enum_to_nick<ApplicationType> (this);
|
||||
}
|
||||
|
||||
internal static ApplicationType from_dtx (string type) {
|
||||
if (type == "System")
|
||||
return SYSTEM;
|
||||
|
||||
if (type == "User")
|
||||
return USER;
|
||||
|
||||
if (type == "PluginKit")
|
||||
return PLUGIN_KIT;
|
||||
|
||||
assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
public class DTXConnection : Object, DTXTransport {
|
||||
public IOStream stream {
|
||||
get;
|
||||
@@ -363,7 +363,7 @@ namespace Frida.Fruity {
|
||||
CLOSED
|
||||
}
|
||||
|
||||
private static Gee.HashMap<ChannelProvider, Future<DTXConnection>> connections;
|
||||
private static Gee.HashMap<HostChannelProvider, Future<DTXConnection>> connections;
|
||||
|
||||
private State _state = OPEN;
|
||||
|
||||
@@ -383,19 +383,21 @@ namespace Frida.Fruity {
|
||||
private const uint32 DTX_FRAGMENT_MAGIC = 0x1f3d5b79U;
|
||||
private const uint MAX_BUFFERED_COUNT = 100;
|
||||
private const size_t MAX_BUFFERED_SIZE = 30 * 1024 * 1024;
|
||||
private const size_t MAX_MESSAGE_SIZE = 1024 * 1024;
|
||||
private const size_t MAX_MESSAGE_SIZE = 128 * 1024 * 1024;
|
||||
private const size_t MAX_FRAGMENT_SIZE = 128 * 1024;
|
||||
private const string REMOTESERVER_ENDPOINT_MODERN = "lockdown:com.apple.instruments.remoteserver.DVTSecureSocketProxy";
|
||||
private const string REMOTESERVER_ENDPOINT_17PLUS = "lockdown:com.apple.instruments.dtservicehub";
|
||||
private const string REMOTESERVER_ENDPOINT_14PLUS = "lockdown:com.apple.instruments.remoteserver.DVTSecureSocketProxy";
|
||||
private const string REMOTESERVER_ENDPOINT_LEGACY = "lockdown:com.apple.instruments.remoteserver?tls=handshake-only";
|
||||
private const string[] REMOTESERVER_ENDPOINT_CANDIDATES = {
|
||||
REMOTESERVER_ENDPOINT_MODERN,
|
||||
REMOTESERVER_ENDPOINT_17PLUS,
|
||||
REMOTESERVER_ENDPOINT_14PLUS,
|
||||
REMOTESERVER_ENDPOINT_LEGACY,
|
||||
};
|
||||
|
||||
public static async DTXConnection obtain (ChannelProvider channel_provider, Cancellable? cancellable)
|
||||
public static async DTXConnection obtain (HostChannelProvider channel_provider, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
if (connections == null)
|
||||
connections = new Gee.HashMap<ChannelProvider, Future<DTXConnection>> ();
|
||||
connections = new Gee.HashMap<HostChannelProvider, Future<DTXConnection>> ();
|
||||
|
||||
while (connections.has_key (channel_provider)) {
|
||||
var future = connections[channel_provider];
|
||||
@@ -442,7 +444,7 @@ namespace Frida.Fruity {
|
||||
throw api_error;
|
||||
}
|
||||
|
||||
public static async void close_all (ChannelProvider channel_provider, Cancellable? cancellable) throws IOError {
|
||||
public static async void close_all (HostChannelProvider channel_provider, Cancellable? cancellable) throws IOError {
|
||||
if (connections == null)
|
||||
return;
|
||||
|
||||
@@ -705,7 +707,9 @@ namespace Frida.Fruity {
|
||||
|
||||
int32 channel_code = message.channel_code;
|
||||
bool is_notification = false;
|
||||
if (message.type == RESULT && channel_code < 0) {
|
||||
if (message.type == INVOKE) {
|
||||
channel_code = -channel_code;
|
||||
} else if (message.type == RESULT && channel_code < 0) {
|
||||
channel_code = -channel_code;
|
||||
is_notification = true;
|
||||
}
|
||||
@@ -866,7 +870,7 @@ namespace Frida.Fruity {
|
||||
|
||||
public class DTXChannel : Object {
|
||||
public signal void invocation (string method_name, DTXArgumentList args, DTXMessageTransportFlags transport_flags);
|
||||
public signal void notification (NSDictionary dict);
|
||||
public signal void notification (NSObject obj);
|
||||
public signal void barrier ();
|
||||
|
||||
public int32 code {
|
||||
@@ -1016,10 +1020,8 @@ namespace Frida.Fruity {
|
||||
}
|
||||
|
||||
internal void handle_notification (DTXMessage message) throws Error {
|
||||
NSDictionary? dict = NSKeyedArchive.decode (message.payload_data) as NSDictionary;
|
||||
if (dict == null)
|
||||
throw new Error.PROTOCOL ("Malformed notification payload");
|
||||
notification (dict);
|
||||
var payload = NSKeyedArchive.decode (message.payload_data);
|
||||
notification (payload);
|
||||
}
|
||||
|
||||
internal void handle_barrier (DTXMessage message) throws Error {
|
||||
@@ -1062,7 +1064,7 @@ namespace Frida.Fruity {
|
||||
}
|
||||
|
||||
public class DTXArgumentList {
|
||||
private Value[] elements;
|
||||
public Value[] elements;
|
||||
|
||||
private DTXArgumentList (owned Value[] elements) {
|
||||
this.elements = (owned) elements;
|
||||
@@ -1101,7 +1103,7 @@ namespace Frida.Fruity {
|
||||
NSObject? obj = NSKeyedArchive.decode (buf);
|
||||
if (obj != null) {
|
||||
var gval = Value (Type.from_instance (obj));
|
||||
gval.set_instance (obj);
|
||||
gval.set_boxed (obj);
|
||||
elements += (owned) gval;
|
||||
} else {
|
||||
var gval = Value (typeof (NSObject));
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -53,6 +53,7 @@ frida_fetch_dyld_symbols (char * output_buffer, const void * dyld_load_address)
|
||||
frida_str_contains (name, "restartWithDyldInCache") ||
|
||||
frida_str_equals (name, "_gProcessInfo") ||
|
||||
frida_str_equals (name, "__ZN5dyld412gProcessInfoE") ||
|
||||
frida_str_equals (name, "__ZL12sProcessInfo") ||
|
||||
frida_str_contains (name, "launchWithClosure") ||
|
||||
frida_str_contains (name, "initializeMainExecutable") ||
|
||||
frida_str_contains (name, "registerThreadHelpers") ||
|
||||
|
||||
+64
-61
@@ -1,6 +1,6 @@
|
||||
[CCode (gir_namespace = "FridaFruityInjector", gir_version = "1.0")]
|
||||
namespace Frida.Fruity.Injector {
|
||||
public static async GadgetDetails inject (owned Gum.DarwinModule module, LLDB.Client lldb, ChannelProvider channel_provider,
|
||||
public static async GadgetDetails inject (owned Gum.DarwinModule module, LLDB.Client lldb, HostChannelProvider channel_provider,
|
||||
Cancellable? cancellable) throws Error, IOError {
|
||||
var session = new Session (module, lldb, channel_provider);
|
||||
return yield session.run (cancellable);
|
||||
@@ -32,7 +32,7 @@ namespace Frida.Fruity.Injector {
|
||||
construct;
|
||||
}
|
||||
|
||||
public ChannelProvider channel_provider {
|
||||
public HostChannelProvider channel_provider {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
@@ -70,7 +70,7 @@ namespace Frida.Fruity.Injector {
|
||||
|
||||
private size_t module_size;
|
||||
|
||||
public Session (Gum.DarwinModule module, LLDB.Client lldb, ChannelProvider channel_provider) {
|
||||
public Session (Gum.DarwinModule module, LLDB.Client lldb, HostChannelProvider channel_provider) {
|
||||
Object (
|
||||
module: module,
|
||||
lldb: lldb,
|
||||
@@ -837,9 +837,11 @@ namespace Frida.Fruity.Injector {
|
||||
|
||||
private async void ensure_libsystem_initialized_for_dyld_v4_and_above (uint64 libdyld_initialize,
|
||||
Cancellable? cancellable) throws GLib.Error {
|
||||
uint64? process_info_ptr = dyld_symbols["_gProcessInfo"];
|
||||
uint64? process_info_ptr = dyld_symbols["__ZL12sProcessInfo"];
|
||||
if (process_info_ptr == null)
|
||||
process_info_ptr = dyld_symbols["__ZN5dyld412gProcessInfoE"];
|
||||
if (process_info_ptr == null)
|
||||
process_info_ptr = dyld_symbols["_gProcessInfo"];
|
||||
|
||||
GDB.Breakpoint init_breakpoint = yield lldb.add_breakpoint (SOFT, libdyld_initialize, 4, cancellable);
|
||||
|
||||
@@ -1181,68 +1183,69 @@ namespace Frida.Fruity.Injector {
|
||||
private const uint8[] SYMBOL_FETCHER_CODE = {
|
||||
0xff, 0x03, 0x02, 0xd1, 0xfc, 0x6f, 0x02, 0xa9, 0xfa, 0x67, 0x03, 0xa9, 0xf8, 0x5f, 0x04, 0xa9, 0xf6, 0x57, 0x05,
|
||||
0xa9, 0xf4, 0x4f, 0x06, 0xa9, 0xfd, 0x7b, 0x07, 0xa9, 0xfd, 0xc3, 0x01, 0x91, 0xf4, 0x03, 0x01, 0xaa, 0xe0, 0x07,
|
||||
0x00, 0xf9, 0x13, 0x00, 0x80, 0xd2, 0x19, 0x00, 0x80, 0xd2, 0x35, 0x80, 0x00, 0x91, 0x3a, 0x10, 0x40, 0xb9, 0xd6,
|
||||
0x22, 0x00, 0x30, 0x1f, 0x20, 0x03, 0xd5, 0xd7, 0x22, 0x00, 0x10, 0x1f, 0x20, 0x03, 0xd5, 0x1a, 0x04, 0x00, 0x34,
|
||||
0x00, 0xf9, 0x13, 0x00, 0x80, 0xd2, 0x19, 0x00, 0x80, 0xd2, 0x35, 0x80, 0x00, 0x91, 0x3a, 0x10, 0x40, 0xb9, 0x16,
|
||||
0x00, 0x00, 0x90, 0xd6, 0xb2, 0x12, 0x91, 0x17, 0x00, 0x00, 0x90, 0xf7, 0xce, 0x12, 0x91, 0x1a, 0x04, 0x00, 0x34,
|
||||
0xa8, 0x02, 0x40, 0xb9, 0x1f, 0x09, 0x00, 0x71, 0xa0, 0x01, 0x00, 0x54, 0x1f, 0x2d, 0x00, 0x71, 0xa0, 0x01, 0x00,
|
||||
0x54, 0x1f, 0x65, 0x00, 0x71, 0x81, 0x01, 0x00, 0x54, 0xb8, 0x22, 0x00, 0x91, 0xe0, 0x03, 0x18, 0xaa, 0xe1, 0x03,
|
||||
0x16, 0xaa, 0xa3, 0x00, 0x00, 0x94, 0x80, 0x01, 0x00, 0x34, 0xb3, 0xa2, 0x41, 0xa9, 0xe8, 0x0b, 0x00, 0xf9, 0x04,
|
||||
0x16, 0xaa, 0xa5, 0x00, 0x00, 0x94, 0x80, 0x01, 0x00, 0x34, 0xb3, 0xa2, 0x41, 0xa9, 0xe8, 0x0b, 0x00, 0xf9, 0x04,
|
||||
0x00, 0x00, 0x14, 0xfc, 0x03, 0x15, 0xaa, 0x02, 0x00, 0x00, 0x14, 0xfb, 0x03, 0x15, 0xaa, 0xa8, 0x06, 0x40, 0xb9,
|
||||
0xb5, 0x02, 0x08, 0x8b, 0x5a, 0x07, 0x00, 0x51, 0x7a, 0xfd, 0xff, 0x35, 0x09, 0x00, 0x00, 0x14, 0xe0, 0x03, 0x18,
|
||||
0xaa, 0xe1, 0x03, 0x17, 0xaa, 0x94, 0x00, 0x00, 0x94, 0x00, 0xff, 0xff, 0x34, 0xa8, 0x0e, 0x40, 0xf9, 0xa9, 0x16,
|
||||
0xaa, 0xe1, 0x03, 0x17, 0xaa, 0x96, 0x00, 0x00, 0x94, 0x00, 0xff, 0xff, 0x34, 0xa8, 0x0e, 0x40, 0xf9, 0xa9, 0x16,
|
||||
0x40, 0xf9, 0x19, 0x01, 0x09, 0xcb, 0xf4, 0xff, 0xff, 0x17, 0x88, 0x02, 0x13, 0xcb, 0x28, 0x03, 0x08, 0x8b, 0x89,
|
||||
0x0b, 0x40, 0xb9, 0x13, 0x01, 0x09, 0x8b, 0x89, 0x13, 0x40, 0xb9, 0x19, 0x01, 0x09, 0x8b, 0x16, 0x17, 0x00, 0x10,
|
||||
0x1f, 0x20, 0x03, 0xd5, 0xe8, 0x07, 0x40, 0xf9, 0xe8, 0x0f, 0x00, 0xf9, 0x35, 0x01, 0x80, 0x52, 0x78, 0x0b, 0x40,
|
||||
0xb9, 0x68, 0x0f, 0x40, 0xb9, 0x1f, 0x03, 0x08, 0x6b, 0xc0, 0x09, 0x00, 0x54, 0xf7, 0x03, 0x18, 0x2a, 0xe8, 0xee,
|
||||
0x7c, 0xd3, 0x68, 0x6a, 0x68, 0xb8, 0x3c, 0x03, 0x08, 0x8b, 0xe0, 0x03, 0x1c, 0xaa, 0xe1, 0x03, 0x16, 0xaa, 0x61,
|
||||
0x00, 0x00, 0x94, 0x60, 0x06, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x41, 0x15, 0x00, 0x70, 0x1f, 0x20, 0x03, 0xd5,
|
||||
0x5c, 0x00, 0x00, 0x94, 0xc0, 0x05, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x61, 0x15, 0x00, 0x50, 0x1f, 0x20, 0x03,
|
||||
0xd5, 0x6f, 0x00, 0x00, 0x94, 0x20, 0x05, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x41, 0x15, 0x00, 0x10, 0x1f, 0x20,
|
||||
0x03, 0xd5, 0x6a, 0x00, 0x00, 0x94, 0x80, 0x04, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x61, 0x15, 0x00, 0x50, 0x1f,
|
||||
0x20, 0x03, 0xd5, 0x4d, 0x00, 0x00, 0x94, 0xe0, 0x03, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x61, 0x15, 0x00, 0x10,
|
||||
0x1f, 0x20, 0x03, 0xd5, 0x48, 0x00, 0x00, 0x94, 0x40, 0x03, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x81, 0x15, 0x00,
|
||||
0x30, 0x1f, 0x20, 0x03, 0xd5, 0x43, 0x00, 0x00, 0x94, 0xa0, 0x02, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x81, 0x15,
|
||||
0x00, 0x70, 0x1f, 0x20, 0x03, 0xd5, 0x5e, 0x00, 0x00, 0x94, 0x00, 0x02, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x21,
|
||||
0x15, 0x00, 0x70, 0x1f, 0x20, 0x03, 0xd5, 0x59, 0x00, 0x00, 0x94, 0x60, 0x01, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa,
|
||||
0xc1, 0x14, 0x00, 0x70, 0x1f, 0x20, 0x03, 0xd5, 0x34, 0x00, 0x00, 0x94, 0xc0, 0x00, 0x00, 0x37, 0xe0, 0x03, 0x1c,
|
||||
0xaa, 0xc1, 0x14, 0x00, 0x50, 0x1f, 0x20, 0x03, 0xd5, 0x2f, 0x00, 0x00, 0x94, 0x40, 0x02, 0x00, 0x34, 0xba, 0x00,
|
||||
0x00, 0x34, 0xe8, 0x0f, 0x40, 0xf9, 0x49, 0x01, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0x68,
|
||||
0x12, 0x17, 0x8b, 0x08, 0x05, 0x40, 0xf9, 0x81, 0x02, 0x08, 0x8b, 0xe0, 0x63, 0x00, 0x91, 0x4d, 0x00, 0x00, 0x94,
|
||||
0xe8, 0x0f, 0x40, 0xf9, 0x15, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe0, 0x63, 0x00, 0x91, 0xe1, 0x03, 0x1c,
|
||||
0xaa, 0x5e, 0x00, 0x00, 0x94, 0x5a, 0x07, 0x00, 0x11, 0x18, 0x07, 0x00, 0x11, 0xb1, 0xff, 0xff, 0x17, 0xe1, 0x23,
|
||||
0x41, 0xa9, 0x49, 0x01, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe0, 0x63, 0x00, 0x91, 0x3e,
|
||||
0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40, 0xf9, 0x29, 0x01, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9,
|
||||
0x21, 0x11, 0x00, 0x70, 0x1f, 0x20, 0x03, 0xd5, 0xe0, 0x63, 0x00, 0x91, 0x4d, 0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40,
|
||||
0xf9, 0xe9, 0x07, 0x40, 0xf9, 0x00, 0x01, 0x09, 0xcb, 0x1f, 0x01, 0x00, 0x39, 0xfd, 0x7b, 0x47, 0xa9, 0xf4, 0x4f,
|
||||
0x46, 0xa9, 0xf6, 0x57, 0x45, 0xa9, 0xf8, 0x5f, 0x44, 0xa9, 0xfa, 0x67, 0x43, 0xa9, 0xfc, 0x6f, 0x42, 0xa9, 0xff,
|
||||
0x03, 0x02, 0x91, 0xc0, 0x03, 0x5f, 0xd6, 0xf6, 0x57, 0xbd, 0xa9, 0xf4, 0x4f, 0x01, 0xa9, 0xfd, 0x7b, 0x02, 0xa9,
|
||||
0xfd, 0x83, 0x00, 0x91, 0xf4, 0x03, 0x01, 0xaa, 0xf3, 0x03, 0x00, 0xaa, 0x35, 0x00, 0x40, 0x39, 0x68, 0x02, 0x40,
|
||||
0x39, 0x28, 0x01, 0x00, 0x34, 0x1f, 0x01, 0x15, 0x6b, 0xa1, 0x00, 0x00, 0x54, 0xe0, 0x03, 0x13, 0xaa, 0xe1, 0x03,
|
||||
0x14, 0xaa, 0x13, 0x00, 0x00, 0x94, 0x80, 0x00, 0x00, 0x37, 0x73, 0x06, 0x00, 0x91, 0xf7, 0xff, 0xff, 0x17, 0x13,
|
||||
0x00, 0x80, 0xd2, 0x7f, 0x02, 0x00, 0xf1, 0xe0, 0x07, 0x9f, 0x1a, 0xfd, 0x7b, 0x42, 0xa9, 0xf4, 0x4f, 0x41, 0xa9,
|
||||
0xf6, 0x57, 0xc3, 0xa8, 0xc0, 0x03, 0x5f, 0xd6, 0x08, 0x14, 0x40, 0x38, 0x29, 0x14, 0x40, 0x38, 0x1f, 0x01, 0x00,
|
||||
0x71, 0x00, 0x11, 0x49, 0x7a, 0x80, 0xff, 0xff, 0x54, 0x1f, 0x01, 0x09, 0x6b, 0xe0, 0x17, 0x9f, 0x1a, 0xc0, 0x03,
|
||||
0x5f, 0xd6, 0x28, 0x00, 0x40, 0x39, 0xa8, 0x00, 0x00, 0x34, 0x21, 0x04, 0x00, 0x91, 0x09, 0x14, 0x40, 0x38, 0x3f,
|
||||
0x01, 0x08, 0x6b, 0x60, 0xff, 0xff, 0x54, 0x1f, 0x01, 0x00, 0x71, 0xe0, 0x17, 0x9f, 0x1a, 0xc0, 0x03, 0x5f, 0xd6,
|
||||
0x09, 0x00, 0x80, 0x52, 0x08, 0x00, 0x40, 0xf9, 0x8a, 0x07, 0x80, 0x52, 0xab, 0x0a, 0x00, 0x10, 0x1f, 0x20, 0x03,
|
||||
0xd5, 0x5f, 0x11, 0x00, 0x31, 0x80, 0x01, 0x00, 0x54, 0x2c, 0x24, 0xca, 0x9a, 0x8c, 0x0d, 0x00, 0x72, 0x2d, 0x01,
|
||||
0x00, 0x12, 0xa0, 0x19, 0x40, 0x7a, 0x29, 0x15, 0x9f, 0x1a, 0x89, 0x00, 0x00, 0x36, 0x8c, 0x1d, 0x40, 0x92, 0x6c,
|
||||
0x69, 0x6c, 0x38, 0x0c, 0x15, 0x00, 0x38, 0x4a, 0x11, 0x00, 0x51, 0xf4, 0xff, 0xff, 0x17, 0x69, 0x00, 0x00, 0x37,
|
||||
0x09, 0x06, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0x08, 0x00, 0x00, 0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0x08, 0x00, 0x40,
|
||||
0xf9, 0x29, 0x00, 0x40, 0x39, 0x89, 0x00, 0x00, 0x34, 0x21, 0x04, 0x00, 0x91, 0x09, 0x15, 0x00, 0x38, 0xfc, 0xff,
|
||||
0xff, 0x17, 0x08, 0x00, 0x00, 0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0x6c, 0x69, 0x62, 0x64, 0x79, 0x6c, 0x64, 0x5f, 0x69,
|
||||
0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x00, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x57, 0x69,
|
||||
0x74, 0x68, 0x44, 0x79, 0x6c, 0x64, 0x49, 0x6e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x00, 0x5f, 0x67, 0x50, 0x72, 0x6f,
|
||||
0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x00, 0x5f, 0x5f, 0x5a, 0x4e, 0x35, 0x64, 0x79, 0x6c, 0x64, 0x34,
|
||||
0x31, 0x32, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x45, 0x00, 0x6c, 0x61, 0x75,
|
||||
0x6e, 0x63, 0x68, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x6f, 0x73, 0x75, 0x72, 0x65, 0x00, 0x69, 0x6e, 0x69, 0x74,
|
||||
0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4d, 0x61, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c,
|
||||
0x65, 0x00, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x48, 0x65, 0x6c,
|
||||
0x70, 0x65, 0x72, 0x73, 0x00, 0x5f, 0x64, 0x6c, 0x6f, 0x70, 0x65, 0x6e, 0x00, 0x5f, 0x73, 0x74, 0x72, 0x63, 0x6d,
|
||||
0x70, 0x00, 0x64, 0x6f, 0x4d, 0x6f, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x73, 0x00, 0x64, 0x6f, 0x47, 0x65, 0x74, 0x44, 0x4f, 0x46, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00,
|
||||
0x64, 0x79, 0x6c, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x5f, 0x5f,
|
||||
0x4c, 0x49, 0x4e, 0x4b, 0x45, 0x44, 0x49, 0x54, 0x00, 0x00, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
|
||||
0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
|
||||
0x0b, 0x40, 0xb9, 0x13, 0x01, 0x09, 0x8b, 0x89, 0x13, 0x40, 0xb9, 0x19, 0x01, 0x09, 0x8b, 0xe8, 0x07, 0x40, 0xf9,
|
||||
0xe8, 0x0f, 0x00, 0xf9, 0x16, 0x00, 0x00, 0x90, 0xd6, 0x22, 0x0f, 0x91, 0x35, 0x01, 0x80, 0x52, 0x78, 0x0b, 0x40,
|
||||
0xb9, 0x68, 0x0f, 0x40, 0xb9, 0x1f, 0x03, 0x08, 0x6b, 0x20, 0x0a, 0x00, 0x54, 0x77, 0x52, 0x38, 0x8b, 0xe8, 0x02,
|
||||
0x40, 0xb9, 0x3c, 0x03, 0x08, 0x8b, 0xe0, 0x03, 0x1c, 0xaa, 0xe1, 0x03, 0x16, 0xaa, 0x65, 0x00, 0x00, 0x94, 0x00,
|
||||
0x07, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0x6c, 0x0f, 0x91, 0x60, 0x00, 0x00, 0x94,
|
||||
0x60, 0x06, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0xc8, 0x0f, 0x91, 0x72, 0x00, 0x00,
|
||||
0x94, 0xc0, 0x05, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0x00, 0x10, 0x91, 0x6d, 0x00,
|
||||
0x00, 0x94, 0x20, 0x05, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0x68, 0x10, 0x91, 0x68,
|
||||
0x00, 0x00, 0x94, 0x80, 0x04, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0xb4, 0x10, 0x91,
|
||||
0x4c, 0x00, 0x00, 0x94, 0xe0, 0x03, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0xfc, 0x10,
|
||||
0x91, 0x47, 0x00, 0x00, 0x94, 0x40, 0x03, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21, 0x60,
|
||||
0x11, 0x91, 0x42, 0x00, 0x00, 0x94, 0xa0, 0x02, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90, 0x21,
|
||||
0xb8, 0x11, 0x91, 0x5c, 0x00, 0x00, 0x94, 0x00, 0x02, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00, 0x90,
|
||||
0x21, 0xd8, 0x11, 0x91, 0x57, 0x00, 0x00, 0x94, 0x60, 0x01, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00, 0x00,
|
||||
0x90, 0x21, 0xf8, 0x11, 0x91, 0x33, 0x00, 0x00, 0x94, 0xc0, 0x00, 0x00, 0x37, 0xe0, 0x03, 0x1c, 0xaa, 0x01, 0x00,
|
||||
0x00, 0x90, 0x21, 0x44, 0x12, 0x91, 0x2e, 0x00, 0x00, 0x94, 0x20, 0x02, 0x00, 0x34, 0xba, 0x00, 0x00, 0x34, 0xe8,
|
||||
0x0f, 0x40, 0xf9, 0x49, 0x01, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe8, 0x06, 0x40, 0xf9,
|
||||
0x81, 0x02, 0x08, 0x8b, 0xe0, 0x63, 0x00, 0x91, 0x4c, 0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40, 0xf9, 0x15, 0x15, 0x00,
|
||||
0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe0, 0x63, 0x00, 0x91, 0xe1, 0x03, 0x1c, 0xaa, 0x5d, 0x00, 0x00, 0x94, 0x5a, 0x07,
|
||||
0x00, 0x11, 0x18, 0x07, 0x00, 0x11, 0xae, 0xff, 0xff, 0x17, 0xe1, 0x23, 0x41, 0xa9, 0x49, 0x01, 0x80, 0x52, 0x09,
|
||||
0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0xe0, 0x63, 0x00, 0x91, 0x3d, 0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40, 0xf9,
|
||||
0x29, 0x01, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0xe8, 0x0f, 0x00, 0xf9, 0x01, 0x00, 0x00, 0x90, 0x21, 0x88, 0x12,
|
||||
0x91, 0xe0, 0x63, 0x00, 0x91, 0x4c, 0x00, 0x00, 0x94, 0xe8, 0x0f, 0x40, 0xf9, 0xe9, 0x07, 0x40, 0xf9, 0x00, 0x01,
|
||||
0x09, 0xcb, 0x1f, 0x01, 0x00, 0x39, 0xfd, 0x7b, 0x47, 0xa9, 0xf4, 0x4f, 0x46, 0xa9, 0xf6, 0x57, 0x45, 0xa9, 0xf8,
|
||||
0x5f, 0x44, 0xa9, 0xfa, 0x67, 0x43, 0xa9, 0xfc, 0x6f, 0x42, 0xa9, 0xff, 0x03, 0x02, 0x91, 0xc0, 0x03, 0x5f, 0xd6,
|
||||
0xf6, 0x57, 0xbd, 0xa9, 0xf4, 0x4f, 0x01, 0xa9, 0xfd, 0x7b, 0x02, 0xa9, 0xfd, 0x83, 0x00, 0x91, 0xf3, 0x03, 0x01,
|
||||
0xaa, 0xf4, 0x03, 0x00, 0xaa, 0x35, 0x00, 0x40, 0x39, 0x96, 0x02, 0x40, 0x39, 0x36, 0x01, 0x00, 0x34, 0xdf, 0x02,
|
||||
0x15, 0x6b, 0xa1, 0x00, 0x00, 0x54, 0xe0, 0x03, 0x14, 0xaa, 0xe1, 0x03, 0x13, 0xaa, 0x12, 0x00, 0x00, 0x94, 0x60,
|
||||
0x00, 0x00, 0x37, 0x94, 0x06, 0x00, 0x91, 0xf7, 0xff, 0xff, 0x17, 0xdf, 0x02, 0x00, 0x71, 0xe0, 0x07, 0x9f, 0x1a,
|
||||
0xfd, 0x7b, 0x42, 0xa9, 0xf4, 0x4f, 0x41, 0xa9, 0xf6, 0x57, 0xc3, 0xa8, 0xc0, 0x03, 0x5f, 0xd6, 0x08, 0x14, 0x40,
|
||||
0x38, 0x29, 0x14, 0x40, 0x38, 0x1f, 0x01, 0x00, 0x71, 0x00, 0x11, 0x49, 0x7a, 0x80, 0xff, 0xff, 0x54, 0x1f, 0x01,
|
||||
0x09, 0x6b, 0xe0, 0x17, 0x9f, 0x1a, 0xc0, 0x03, 0x5f, 0xd6, 0x28, 0x00, 0x40, 0x39, 0xa8, 0x00, 0x00, 0x34, 0x21,
|
||||
0x04, 0x00, 0x91, 0x09, 0x14, 0x40, 0x38, 0x3f, 0x01, 0x08, 0x6b, 0x60, 0xff, 0xff, 0x54, 0x1f, 0x01, 0x00, 0x71,
|
||||
0xe0, 0x17, 0x9f, 0x1a, 0xc0, 0x03, 0x5f, 0xd6, 0x09, 0x00, 0x80, 0x52, 0x08, 0x00, 0x40, 0xf9, 0x8a, 0x07, 0x80,
|
||||
0x52, 0x0b, 0x00, 0x00, 0x90, 0x6b, 0x01, 0x13, 0x91, 0x5f, 0x11, 0x00, 0x31, 0x80, 0x01, 0x00, 0x54, 0x2c, 0x24,
|
||||
0xca, 0x9a, 0x8c, 0x0d, 0x40, 0x92, 0x2d, 0x01, 0x00, 0x12, 0x9f, 0x01, 0x00, 0x71, 0xa0, 0x19, 0x40, 0x7a, 0x29,
|
||||
0x15, 0x9f, 0x1a, 0x69, 0x00, 0x00, 0x36, 0x6c, 0x69, 0x6c, 0x38, 0x0c, 0x15, 0x00, 0x38, 0x4a, 0x11, 0x00, 0x51,
|
||||
0xf4, 0xff, 0xff, 0x17, 0x69, 0x00, 0x00, 0x37, 0x09, 0x06, 0x80, 0x52, 0x09, 0x15, 0x00, 0x38, 0x08, 0x00, 0x00,
|
||||
0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0x08, 0x00, 0x40, 0xf9, 0x29, 0x00, 0x40, 0x39, 0x89, 0x00, 0x00, 0x34, 0x21, 0x04,
|
||||
0x00, 0x91, 0x09, 0x15, 0x00, 0x38, 0xfc, 0xff, 0xff, 0x17, 0x08, 0x00, 0x00, 0xf9, 0xc0, 0x03, 0x5f, 0xd6, 0x6c,
|
||||
0x69, 0x62, 0x64, 0x79, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x00, 0x72,
|
||||
0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x57, 0x69, 0x74, 0x68, 0x44, 0x79, 0x6c, 0x64, 0x49, 0x6e, 0x43, 0x61, 0x63,
|
||||
0x68, 0x65, 0x00, 0x5f, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x00, 0x5f, 0x5f,
|
||||
0x5a, 0x4e, 0x35, 0x64, 0x79, 0x6c, 0x64, 0x34, 0x31, 0x32, 0x67, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x49,
|
||||
0x6e, 0x66, 0x6f, 0x45, 0x00, 0x5f, 0x5f, 0x5a, 0x4c, 0x31, 0x32, 0x73, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73,
|
||||
0x49, 0x6e, 0x66, 0x6f, 0x00, 0x6c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x57, 0x69, 0x74, 0x68, 0x43, 0x6c, 0x6f, 0x73,
|
||||
0x75, 0x72, 0x65, 0x00, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4d, 0x61, 0x69, 0x6e, 0x45,
|
||||
0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x54,
|
||||
0x68, 0x72, 0x65, 0x61, 0x64, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x73, 0x00, 0x5f, 0x64, 0x6c, 0x6f, 0x70, 0x65,
|
||||
0x6e, 0x00, 0x5f, 0x73, 0x74, 0x72, 0x63, 0x6d, 0x70, 0x00, 0x64, 0x6f, 0x4d, 0x6f, 0x64, 0x49, 0x6e, 0x69, 0x74,
|
||||
0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x64, 0x6f, 0x47, 0x65, 0x74, 0x44, 0x4f, 0x46, 0x53,
|
||||
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x00, 0x64, 0x79, 0x6c, 0x64, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x00, 0x5f,
|
||||
0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x5f, 0x5f, 0x4c, 0x49, 0x4e, 0x4b, 0x45, 0x44, 0x49, 0x54, 0x00, 0x00, 0x00,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66
|
||||
};
|
||||
|
||||
private async SymbolSet resolve_symbols (SymbolQuery query, Cancellable? cancellable) throws GLib.Error {
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
namespace Frida {
|
||||
using CoreFoundation;
|
||||
using Darwin.XNU;
|
||||
|
||||
internal class IORegistry {
|
||||
private MachPort main_port;
|
||||
|
||||
public static IORegistry open () throws Error {
|
||||
MachPort port;
|
||||
kern_check (Darwin.IOKit.main_port (MachPort.NULL, out port));
|
||||
return new IORegistry (port);
|
||||
}
|
||||
|
||||
private IORegistry (MachPort main_port) {
|
||||
this.main_port = main_port;
|
||||
}
|
||||
|
||||
public IOIterator<IORegistryEntry> matching_services (owned MutableDictionary matching_dict) throws Error {
|
||||
Darwin.IOKit.IOIterator h;
|
||||
kern_check (Darwin.IOKit.get_matching_services (main_port, matching_dict, out h));
|
||||
return new IOIterator<IORegistryEntry> ((owned) h);
|
||||
}
|
||||
}
|
||||
|
||||
internal class IORegistryEntry : GLib.Object {
|
||||
public IOObject io_object {
|
||||
get;
|
||||
construct;
|
||||
}
|
||||
|
||||
internal IORegistryEntry (IOObject obj) {
|
||||
GLib.Object (io_object: obj);
|
||||
}
|
||||
|
||||
public MutableDictionary get_properties () throws Error {
|
||||
MutableDictionary properties;
|
||||
kern_check (unwrap ().create_cf_properties (out properties, null, 0));
|
||||
return properties;
|
||||
}
|
||||
|
||||
public string? get_string_property (string key) {
|
||||
var v = (String) unwrap ().create_cf_property (String.make (key), null, 0);
|
||||
return (v != null) ? v.to_string () : null;
|
||||
}
|
||||
|
||||
public IORegistryEntry parent (string plane) throws Error {
|
||||
Darwin.IOKit.IOObject h;
|
||||
kern_check (unwrap ().get_parent_entry (plane, out h));
|
||||
return new IORegistryEntry (new IOObject ((owned) h));
|
||||
}
|
||||
|
||||
private unowned Darwin.IOKit.IORegistryEntry unwrap () {
|
||||
return (Darwin.IOKit.IORegistryEntry) io_object.handle;
|
||||
}
|
||||
}
|
||||
|
||||
internal class IOIterator<T> {
|
||||
private Darwin.IOKit.IOIterator handle;
|
||||
|
||||
internal IOIterator (owned Darwin.IOKit.IOIterator handle) {
|
||||
this.handle = (owned) handle;
|
||||
}
|
||||
|
||||
public IOIterator<T> iterator () {
|
||||
return this;
|
||||
}
|
||||
|
||||
public T? next_value () {
|
||||
Darwin.IOKit.IOObject h = handle.next ();
|
||||
if (h == Darwin.IOKit.IOObject.NULL)
|
||||
return null;
|
||||
return GLib.Object.new (typeof (T), io_object: new IOObject ((owned) h));
|
||||
}
|
||||
}
|
||||
|
||||
internal class IOObject {
|
||||
internal Darwin.IOKit.IOObject handle;
|
||||
|
||||
internal IOObject (owned Darwin.IOKit.IOObject handle) {
|
||||
this.handle = (owned) handle;
|
||||
}
|
||||
}
|
||||
|
||||
private void kern_check (KernReturn result) throws Error {
|
||||
if (result != KernReturn.SUCCESS)
|
||||
throw new Error.NOT_SUPPORTED ("%s", mach_error_string (result));
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,11 @@ namespace Frida.Fruity {
|
||||
}
|
||||
|
||||
public class NSNumber : NSObject {
|
||||
public Kind kind {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool boolean {
|
||||
get;
|
||||
private set;
|
||||
@@ -33,14 +38,44 @@ namespace Frida.Fruity {
|
||||
private set;
|
||||
}
|
||||
|
||||
public double number {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public enum Kind {
|
||||
BOOLEAN,
|
||||
INTEGER,
|
||||
FLOAT,
|
||||
DOUBLE,
|
||||
}
|
||||
|
||||
public NSNumber.from_boolean (bool val) {
|
||||
kind = BOOLEAN;
|
||||
boolean = val;
|
||||
integer = val ? 1 : 0;
|
||||
number = val ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
public NSNumber.from_integer (int64 val) {
|
||||
kind = INTEGER;
|
||||
boolean = (val != 0) ? true : false;
|
||||
integer = val;
|
||||
number = val;
|
||||
}
|
||||
|
||||
public NSNumber.from_float (float val) {
|
||||
kind = FLOAT;
|
||||
boolean = (val != 0.0f) ? true : false;
|
||||
integer = (int64) val;
|
||||
number = val;
|
||||
}
|
||||
|
||||
public NSNumber.from_double (double val) {
|
||||
kind = DOUBLE;
|
||||
boolean = (val != 0.0) ? true : false;
|
||||
integer = (int64) val;
|
||||
number = val;
|
||||
}
|
||||
|
||||
public override uint hash () {
|
||||
@@ -51,7 +86,21 @@ namespace Frida.Fruity {
|
||||
var other_number = other as NSNumber;
|
||||
if (other_number == null)
|
||||
return false;
|
||||
return other_number.integer == integer;
|
||||
|
||||
if (other_number.kind != kind)
|
||||
return false;
|
||||
|
||||
switch (kind) {
|
||||
case BOOLEAN:
|
||||
return other_number.boolean == boolean;
|
||||
case INTEGER:
|
||||
return other_number.integer == integer;
|
||||
case FLOAT:
|
||||
case DOUBLE:
|
||||
return other_number.number == number;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override string to_string () {
|
||||
@@ -85,6 +134,32 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class NSData : NSObject {
|
||||
public Bytes bytes {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public NSData (Bytes bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public override uint hash () {
|
||||
return bytes.hash ();
|
||||
}
|
||||
|
||||
public override bool is_equal_to (NSObject other) {
|
||||
var other_data = other as NSData;
|
||||
if (other_data == null)
|
||||
return false;
|
||||
return other_data.bytes.compare (bytes) == 0;
|
||||
}
|
||||
|
||||
public override string to_string () {
|
||||
return "NSData";
|
||||
}
|
||||
}
|
||||
|
||||
public class NSDictionary : NSObject {
|
||||
public int size {
|
||||
get {
|
||||
@@ -198,6 +273,10 @@ namespace Frida.Fruity {
|
||||
public NSArray (Gee.ArrayList<NSObject>? storage = null) {
|
||||
this.storage = (storage != null) ? storage : new Gee.ArrayList<NSObject> (NSObject.equal_func);
|
||||
}
|
||||
|
||||
public void add_object (NSObject obj) {
|
||||
storage.add (obj);
|
||||
}
|
||||
}
|
||||
|
||||
public class NSDate : NSObject {
|
||||
@@ -242,11 +321,23 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
public class DTTapMessage : NSObject {
|
||||
public NSDictionary plist {
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public DTTapMessage (NSDictionary plist) {
|
||||
this.plist = plist;
|
||||
}
|
||||
}
|
||||
|
||||
namespace NSKeyedArchive {
|
||||
private Gee.HashMap<Type, EncodeFunc> encoders;
|
||||
private Gee.HashMap<string, DecodeFunc> decoders;
|
||||
|
||||
private const string[] DICTIONARY_CLASS = { "NSDictionary", "NSObject" };
|
||||
private const string[] ARRAY_CLASS = { "NSArray", "NSObject" };
|
||||
|
||||
[CCode (has_target = false)]
|
||||
private delegate PlistUid EncodeFunc (NSObject instance, EncodingContext ctx);
|
||||
@@ -319,9 +410,18 @@ namespace Frida.Fruity {
|
||||
if (t == typeof (int64))
|
||||
return new NSNumber.from_integer (val.get_int64 ());
|
||||
|
||||
if (t == typeof (float))
|
||||
return new NSNumber.from_float (val.get_float ());
|
||||
|
||||
if (t == typeof (double))
|
||||
return new NSNumber.from_double (val.get_double ());
|
||||
|
||||
if (t == typeof (string))
|
||||
return new NSString (val.get_string ());
|
||||
|
||||
if (t == typeof (Bytes))
|
||||
return new NSData ((Bytes) val.get_boxed ());
|
||||
|
||||
if (t == typeof (PlistDict)) {
|
||||
var instance = (PlistDict) val.get_object ();
|
||||
var klass = objects.get_dict ((int) instance.get_uid ("$class").uid);
|
||||
@@ -354,6 +454,7 @@ namespace Frida.Fruity {
|
||||
encoders[typeof (NSNumber)] = encode_number;
|
||||
encoders[typeof (NSString)] = encode_string;
|
||||
encoders[typeof (NSDictionary)] = encode_dictionary;
|
||||
encoders[typeof (NSArray)] = encode_array;
|
||||
}
|
||||
|
||||
private static void ensure_decoders_registered () {
|
||||
@@ -365,11 +466,41 @@ namespace Frida.Fruity {
|
||||
decoders["NSArray"] = decode_array;
|
||||
decoders["NSDate"] = decode_date;
|
||||
decoders["NSError"] = decode_error;
|
||||
decoders["DTTapMessage"] = decode_tap_message;
|
||||
decoders["DTSysmonTapMessage"] = decode_tap_message;
|
||||
decoders["DTActivityTraceTapMessage"] = decode_tap_message;
|
||||
decoders["DTTapStatusMessage"] = decode_tap_message;
|
||||
decoders["DTTapHeartbeatMessage"] = decode_tap_message;
|
||||
decoders["DTKTraceTapMessage"] = decode_tap_message;
|
||||
}
|
||||
|
||||
private static PlistUid encode_number (NSObject instance, EncodingContext ctx) {
|
||||
int64 val = ((NSNumber) instance).integer;
|
||||
var n = (NSNumber) instance;
|
||||
switch (n.kind) {
|
||||
case BOOLEAN:
|
||||
return encode_boolean (n.boolean, ctx);
|
||||
case INTEGER:
|
||||
return encode_integer (n.integer, ctx);
|
||||
case FLOAT:
|
||||
return encode_float (n.integer, ctx);
|
||||
case DOUBLE:
|
||||
return encode_double (n.integer, ctx);
|
||||
}
|
||||
assert_not_reached ();
|
||||
}
|
||||
|
||||
private static PlistUid encode_boolean (bool val, EncodingContext ctx) {
|
||||
var uid = ctx.find_existing_object (e => e.holds (typeof (bool)) && e.get_boolean () == val);
|
||||
if (uid != null)
|
||||
return uid;
|
||||
|
||||
var objects = ctx.objects;
|
||||
uid = new PlistUid (objects.length);
|
||||
objects.add_boolean (val);
|
||||
return uid;
|
||||
}
|
||||
|
||||
private static PlistUid encode_integer (int64 val, EncodingContext ctx) {
|
||||
var uid = ctx.find_existing_object (e => e.holds (typeof (int64)) && e.get_int64 () == val);
|
||||
if (uid != null)
|
||||
return uid;
|
||||
@@ -380,6 +511,28 @@ namespace Frida.Fruity {
|
||||
return uid;
|
||||
}
|
||||
|
||||
private static PlistUid encode_float (float val, EncodingContext ctx) {
|
||||
var uid = ctx.find_existing_object (e => e.holds (typeof (float)) && e.get_float () == val);
|
||||
if (uid != null)
|
||||
return uid;
|
||||
|
||||
var objects = ctx.objects;
|
||||
uid = new PlistUid (objects.length);
|
||||
objects.add_float (val);
|
||||
return uid;
|
||||
}
|
||||
|
||||
private static PlistUid encode_double (double val, EncodingContext ctx) {
|
||||
var uid = ctx.find_existing_object (e => e.holds (typeof (double)) && e.get_double () == val);
|
||||
if (uid != null)
|
||||
return uid;
|
||||
|
||||
var objects = ctx.objects;
|
||||
uid = new PlistUid (objects.length);
|
||||
objects.add_double (val);
|
||||
return uid;
|
||||
}
|
||||
|
||||
private static PlistUid encode_string (NSObject instance, EncodingContext ctx) {
|
||||
string str = ((NSString) instance).str;
|
||||
|
||||
@@ -451,6 +604,21 @@ namespace Frida.Fruity {
|
||||
}
|
||||
}
|
||||
|
||||
private static PlistUid encode_array (NSObject instance, EncodingContext ctx) {
|
||||
NSArray array = (NSArray) instance;
|
||||
|
||||
var object = new PlistDict ();
|
||||
var uid = ctx.add_object (object);
|
||||
|
||||
var objs = new PlistArray ();
|
||||
foreach (var element in array.elements)
|
||||
objs.add_uid (encode_value (element, ctx));
|
||||
object.set_array ("NS.objects", objs);
|
||||
object.set_uid ("$class", ctx.get_class (ARRAY_CLASS));
|
||||
|
||||
return uid;
|
||||
}
|
||||
|
||||
private static NSObject decode_array (PlistDict instance, DecodingContext ctx) throws Error, PlistError {
|
||||
var objs = instance.get_array ("NS.objects");
|
||||
|
||||
@@ -486,6 +654,10 @@ namespace Frida.Fruity {
|
||||
return new NSError (domain, code, (NSDictionary) user_info);
|
||||
}
|
||||
|
||||
private static NSObject decode_tap_message (PlistDict instance, DecodingContext ctx) throws Error, PlistError {
|
||||
return new DTTapMessage ((NSDictionary) decode_value (instance.get_uid ("DTTapMessagePlist"), ctx));
|
||||
}
|
||||
|
||||
private class EncodingContext {
|
||||
public PlistArray objects;
|
||||
|
||||
|
||||
@@ -1573,6 +1573,12 @@ namespace Frida.Fruity {
|
||||
if (t == typeof (int64))
|
||||
return (uint) v.get_int64 ();
|
||||
|
||||
if (t == typeof (float))
|
||||
return (uint) v.get_float ();
|
||||
|
||||
if (t == typeof (double))
|
||||
return (uint) v.get_double ();
|
||||
|
||||
if (t == typeof (string))
|
||||
return str_hash (v.get_string ());
|
||||
|
||||
@@ -1598,6 +1604,12 @@ namespace Frida.Fruity {
|
||||
if (t == typeof (int64))
|
||||
return a.get_int64 () == b.get_int64 ();
|
||||
|
||||
if (t == typeof (float))
|
||||
return a.get_float () == b.get_float ();
|
||||
|
||||
if (t == typeof (double))
|
||||
return a.get_double () == b.get_double ();
|
||||
|
||||
if (t == typeof (string))
|
||||
return a.get_string () == b.get_string ();
|
||||
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
|
||||
namespace Frida.Fruity {
|
||||
using Darwin.GCD;
|
||||
using Darwin.DNSSD;
|
||||
using Darwin.Net;
|
||||
|
||||
public class DarwinPairingBrowser : Object, PairingBrowser {
|
||||
private MainContext main_context;
|
||||
private DispatchQueue dispatch_queue = new DispatchQueue ("re.frida.fruity.browser-queue", DispatchQueueAttr.SERIAL);
|
||||
|
||||
private DNSService dns_connection;
|
||||
private DNSService browse_session;
|
||||
private TaskQueue task_queue;
|
||||
|
||||
private Gee.List<PairingServiceDetails> current_batch = new Gee.ArrayList<PairingServiceDetails> ();
|
||||
|
||||
construct {
|
||||
main_context = MainContext.ref_thread_default ();
|
||||
|
||||
dispatch_queue.dispatch_async (() => {
|
||||
DNSService.create_connection (out dns_connection);
|
||||
dns_connection.set_dispatch_queue (dispatch_queue);
|
||||
|
||||
DNSService session = dns_connection;
|
||||
DNSService.browse (ref session, PrivateFive | ShareConnection, 0, PAIRING_REGTYPE, PAIRING_DOMAIN,
|
||||
on_browse_reply);
|
||||
browse_session = session;
|
||||
|
||||
task_queue = new TaskQueue (this);
|
||||
});
|
||||
}
|
||||
|
||||
~DarwinPairingBrowser () {
|
||||
dispatch_queue.dispatch_sync (() => {
|
||||
browse_session.deallocate ();
|
||||
dns_connection.deallocate ();
|
||||
});
|
||||
}
|
||||
|
||||
private void on_browse_reply (DNSService sd_ref, DNSService.Flags flags, uint32 interface_index,
|
||||
DNSService.ErrorType error_code, string service_name, string regtype, string reply_domain) {
|
||||
if (error_code != NoError)
|
||||
return;
|
||||
|
||||
var interface_name_buf = new char[IFNAMSIZ];
|
||||
unowned string interface_name = if_indextoname (interface_index, interface_name_buf);
|
||||
|
||||
var service = new DarwinPairingServiceDetails (service_name, interface_index, interface_name, task_queue);
|
||||
current_batch.add (service);
|
||||
|
||||
if ((flags & DNSService.Flags.MoreComing) != 0)
|
||||
return;
|
||||
|
||||
var services = current_batch;
|
||||
current_batch = new Gee.ArrayList<PairingServiceDetails> ();
|
||||
|
||||
schedule_on_frida_thread (() => {
|
||||
services_discovered (services.to_array ());
|
||||
return Source.REMOVE;
|
||||
});
|
||||
}
|
||||
|
||||
private void schedule_on_frida_thread (owned SourceFunc function) {
|
||||
var source = new IdleSource ();
|
||||
source.set_callback ((owned) function);
|
||||
source.attach (main_context);
|
||||
}
|
||||
|
||||
private class TaskQueue : Object, DNSServiceProvider {
|
||||
private weak DarwinPairingBrowser parent;
|
||||
|
||||
private DNSServiceTask? current = null;
|
||||
private Gee.Deque<DNSServiceTask> pending = new Gee.ArrayQueue<DNSServiceTask> ();
|
||||
|
||||
public TaskQueue (DarwinPairingBrowser parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
private async T with_dns_service<T> (DNSServiceTask task, Cancellable? cancellable) throws Error, IOError {
|
||||
var promise = new Promise<Object> ();
|
||||
task.set_data ("promise", promise);
|
||||
pending.offer_tail (task);
|
||||
|
||||
maybe_start_next ();
|
||||
|
||||
return (T) yield promise.future.wait_async (cancellable);
|
||||
}
|
||||
|
||||
private void maybe_start_next () {
|
||||
if (current != null)
|
||||
return;
|
||||
|
||||
DNSServiceTask? task = pending.poll_head ();
|
||||
if (task == null)
|
||||
return;
|
||||
current = task;
|
||||
|
||||
parent.dispatch_queue.dispatch_async (() => {
|
||||
current.dns_connection = parent.dns_connection;
|
||||
current.on_complete = on_complete;
|
||||
current.start ();
|
||||
});
|
||||
}
|
||||
|
||||
private void on_complete (Object? result, Error? error) {
|
||||
parent.schedule_on_frida_thread (() => {
|
||||
Promise<Object> promise = current.steal_data ("promise");
|
||||
|
||||
if (error != null)
|
||||
promise.reject (error);
|
||||
else
|
||||
promise.resolve (result);
|
||||
|
||||
current = null;
|
||||
maybe_start_next ();
|
||||
|
||||
return Source.REMOVE;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private interface DNSServiceProvider : Object {
|
||||
public abstract async T with_dns_service<T> (DNSServiceTask task, Cancellable? cancellable) throws Error, IOError;
|
||||
}
|
||||
|
||||
private abstract class DNSServiceTask : Object {
|
||||
internal DNSService? dns_connection;
|
||||
internal CompleteFunc? on_complete;
|
||||
|
||||
protected DNSService? session;
|
||||
|
||||
public delegate void CompleteFunc (Object? result, Error? error);
|
||||
|
||||
public abstract void start ();
|
||||
|
||||
protected void complete (Object? result, Error? error) {
|
||||
if (session != null && session != dns_connection) {
|
||||
session.deallocate ();
|
||||
session = null;
|
||||
}
|
||||
|
||||
on_complete (result, error);
|
||||
on_complete = null;
|
||||
}
|
||||
}
|
||||
|
||||
public class DarwinPairingServiceDetails : Object, PairingServiceDetails {
|
||||
public string name {
|
||||
get { return _name; }
|
||||
}
|
||||
|
||||
public uint interface_index {
|
||||
get { return _interface_index; }
|
||||
}
|
||||
|
||||
public string interface_name {
|
||||
get { return _interface_name; }
|
||||
}
|
||||
|
||||
private string _name;
|
||||
private uint _interface_index;
|
||||
private string _interface_name;
|
||||
|
||||
private DNSServiceProvider dns;
|
||||
|
||||
internal DarwinPairingServiceDetails (string name, uint interface_index, string interface_name, DNSServiceProvider dns) {
|
||||
_name = name;
|
||||
_interface_index = interface_index;
|
||||
_interface_name = interface_name;
|
||||
|
||||
this.dns = dns;
|
||||
}
|
||||
|
||||
public async Gee.List<PairingServiceHost> resolve (Cancellable? cancellable) throws Error, IOError {
|
||||
var task = new ResolveTask (this);
|
||||
return yield dns.with_dns_service (task, cancellable);
|
||||
}
|
||||
|
||||
private class ResolveTask : DNSServiceTask {
|
||||
private weak DarwinPairingServiceDetails parent;
|
||||
|
||||
private Gee.List<PairingServiceHost> hosts = new Gee.ArrayList<PairingServiceHost> ();
|
||||
|
||||
public ResolveTask (DarwinPairingServiceDetails parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public override void start () {
|
||||
session = dns_connection;
|
||||
DNSService.resolve (ref session, PrivateFive | ShareConnection, parent.interface_index, parent.name,
|
||||
PAIRING_REGTYPE, PAIRING_DOMAIN, on_resolve_reply);
|
||||
}
|
||||
|
||||
private void on_resolve_reply (DNSService sd_ref, DNSService.Flags flags, uint32 interface_index,
|
||||
DNSService.ErrorType error_code, string fullname, string hosttarget, uint16 port,
|
||||
uint8[] raw_txt_record) {
|
||||
if (error_code != NoError) {
|
||||
complete (null,
|
||||
new Error.TRANSPORT ("Unable to resolve service '%s' on interface %s",
|
||||
parent.name, parent.interface_name));
|
||||
return;
|
||||
}
|
||||
|
||||
var txt_record = new Gee.ArrayList<string> ();
|
||||
size_t cursor = 0;
|
||||
size_t remaining = raw_txt_record.length;
|
||||
while (remaining != 0) {
|
||||
size_t len = raw_txt_record[cursor];
|
||||
cursor++;
|
||||
remaining--;
|
||||
if (len > remaining)
|
||||
break;
|
||||
|
||||
unowned string raw_val = (string) raw_txt_record[cursor:cursor + len];
|
||||
string val = raw_val.make_valid ((ssize_t) len);
|
||||
txt_record.add (val);
|
||||
|
||||
cursor += len;
|
||||
remaining -= len;
|
||||
}
|
||||
|
||||
hosts.add (new DarwinPairingServiceHost (parent, hosttarget, uint16.from_big_endian (port), txt_record,
|
||||
parent.dns));
|
||||
|
||||
if ((flags & DNSService.Flags.MoreComing) == 0)
|
||||
complete (hosts, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DarwinPairingServiceHost : Object, PairingServiceHost {
|
||||
public string name {
|
||||
get { return _name; }
|
||||
}
|
||||
|
||||
public uint16 port {
|
||||
get { return _port; }
|
||||
}
|
||||
|
||||
public Gee.List<string> txt_record {
|
||||
get { return _txt_record; }
|
||||
}
|
||||
|
||||
private string _name;
|
||||
private uint16 _port;
|
||||
private Gee.List<string> _txt_record;
|
||||
|
||||
private PairingServiceDetails service;
|
||||
private DNSServiceProvider dns;
|
||||
|
||||
internal DarwinPairingServiceHost (PairingServiceDetails service, string name, uint16 port, Gee.List<string> txt_record,
|
||||
DNSServiceProvider dns) {
|
||||
_name = name;
|
||||
_port = port;
|
||||
_txt_record = txt_record;
|
||||
|
||||
this.service = service;
|
||||
this.dns = dns;
|
||||
}
|
||||
|
||||
public async Gee.List<InetSocketAddress> resolve (Cancellable? cancellable) throws Error, IOError {
|
||||
var task = new ResolveTask (this);
|
||||
return yield dns.with_dns_service (task, cancellable);
|
||||
}
|
||||
|
||||
private class ResolveTask : DNSServiceTask {
|
||||
private weak DarwinPairingServiceHost parent;
|
||||
|
||||
private Gee.List<InetSocketAddress> addresses = new Gee.ArrayList<InetSocketAddress> ();
|
||||
|
||||
public ResolveTask (DarwinPairingServiceHost parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public override void start () {
|
||||
session = dns_connection;
|
||||
DNSService.get_addr_info (ref session, PrivateFive | ShareConnection, parent.service.interface_index, IPv6,
|
||||
parent.name, on_info_reply);
|
||||
}
|
||||
|
||||
private void on_info_reply (DNSService sd_ref, DNSService.Flags flags, uint32 interface_index,
|
||||
DNSService.ErrorType error_code, string hostname, void * address, uint32 ttl) {
|
||||
if (error_code != NoError) {
|
||||
complete (null,
|
||||
new Error.TRANSPORT ("Unable to resolve host '%s' on interface %s",
|
||||
parent.name, parent.service.interface_name));
|
||||
return;
|
||||
}
|
||||
|
||||
addresses.add ((InetSocketAddress) SocketAddress.from_native (address, sizeof (Posix.SockAddrIn6)));
|
||||
|
||||
if ((flags & DNSService.Flags.MoreComing) == 0)
|
||||
complete (addresses, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,426 @@
|
||||
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
|
||||
namespace Frida.Fruity {
|
||||
public sealed class LinuxTunnelFinder : Object, TunnelFinder {
|
||||
public async Tunnel? find (string udid, Cancellable? cancellable) throws Error, IOError {
|
||||
NcmPeer? peer = yield locate_ncm_peer (udid, cancellable);
|
||||
if (peer == null)
|
||||
return null;
|
||||
|
||||
var bootstrap_disco = yield DiscoveryService.open (
|
||||
yield peer.open_tcp_connection (58783, cancellable), cancellable);
|
||||
|
||||
var tunnel_service = bootstrap_disco.get_service ("com.apple.internal.dt.coredevice.untrusted.tunnelservice");
|
||||
var pairing_transport = new XpcPairingTransport (yield peer.open_tcp_connection (tunnel_service.port, cancellable));
|
||||
var pairing_service = yield PairingService.open (pairing_transport, cancellable);
|
||||
|
||||
TunnelConnection tc = yield pairing_service.open_tunnel (peer.address, cancellable);
|
||||
|
||||
var disco = yield DiscoveryService.open (yield tc.open_connection (tc.remote_rsd_port, cancellable), cancellable);
|
||||
|
||||
return new LinuxTunnel (tc, disco);
|
||||
}
|
||||
|
||||
private static async NcmPeer? locate_ncm_peer (string udid, Cancellable? cancellable) throws Error, IOError {
|
||||
var device_ifaddrs = new Gee.ArrayList<unowned Linux.Network.IfAddrs> ();
|
||||
var fruit_finder = FruitFinder.make_default ();
|
||||
string raw_udid = udid.replace ("-", "");
|
||||
Linux.Network.IfAddrs ifaddrs;
|
||||
Linux.Network.getifaddrs (out ifaddrs);
|
||||
for (unowned Linux.Network.IfAddrs candidate = ifaddrs; candidate != null; candidate = candidate.ifa_next) {
|
||||
if (candidate.ifa_addr.sa_family != Posix.AF_INET6)
|
||||
continue;
|
||||
|
||||
string? candidate_udid = fruit_finder.udid_from_iface (candidate.ifa_name);
|
||||
if (candidate_udid != raw_udid)
|
||||
continue;
|
||||
|
||||
device_ifaddrs.add (candidate);
|
||||
}
|
||||
if (device_ifaddrs.is_empty)
|
||||
return null;
|
||||
|
||||
var sockets = new Gee.ArrayList<Socket> ();
|
||||
var sources = new Gee.ArrayList<Source> ();
|
||||
var readable_sockets = new Gee.ArrayQueue<Socket> ();
|
||||
bool timed_out = false;
|
||||
bool waiting = false;
|
||||
|
||||
var remote_address = new InetSocketAddress.from_string ("ff02::fb", 5353);
|
||||
var remoted_mdns_request = make_remoted_mdns_request ();
|
||||
var main_context = MainContext.get_thread_default ();
|
||||
|
||||
foreach (unowned Linux.Network.IfAddrs ifaddr in device_ifaddrs) {
|
||||
try {
|
||||
var sock = new Socket (IPV6, DATAGRAM, UDP);
|
||||
sock.bind (SocketAddress.from_native ((void *) ifaddr.ifa_addr, sizeof (Posix.SockAddrIn6)), false);
|
||||
sock.send_to (remote_address, remoted_mdns_request.get_data (), cancellable);
|
||||
|
||||
var source = sock.create_source (IN, cancellable);
|
||||
source.set_callback (() => {
|
||||
readable_sockets.offer (sock);
|
||||
if (waiting)
|
||||
locate_ncm_peer.callback ();
|
||||
return Source.REMOVE;
|
||||
});
|
||||
source.attach (main_context);
|
||||
|
||||
sockets.add (sock);
|
||||
sources.add (source);
|
||||
} catch (GLib.Error e) {
|
||||
}
|
||||
}
|
||||
|
||||
var timeout_source = new TimeoutSource.seconds (2);
|
||||
timeout_source.set_callback (() => {
|
||||
timed_out = true;
|
||||
if (waiting)
|
||||
locate_ncm_peer.callback ();
|
||||
return Source.REMOVE;
|
||||
});
|
||||
timeout_source.attach (main_context);
|
||||
sources.add (timeout_source);
|
||||
|
||||
Socket? sock;
|
||||
while ((sock = readable_sockets.poll ()) == null && !timed_out) {
|
||||
waiting = true;
|
||||
yield;
|
||||
waiting = false;
|
||||
}
|
||||
|
||||
foreach (var source in sources)
|
||||
source.destroy ();
|
||||
|
||||
if (sock == null && timed_out)
|
||||
throw new Error.TIMED_OUT ("Unexpectedly timed out while waiting for mDNS reply");
|
||||
|
||||
InetSocketAddress sender;
|
||||
try {
|
||||
SocketAddress raw_sender;
|
||||
var response_buf = new uint8[2048];
|
||||
sock.receive_from (out raw_sender, response_buf, cancellable);
|
||||
sender = (InetSocketAddress) raw_sender;
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.TRANSPORT ("%s", e.message);
|
||||
}
|
||||
|
||||
return new NcmPeer ("%s%%%u".printf (sender.address.to_string (), sender.scope_id));
|
||||
}
|
||||
|
||||
private static Bytes make_remoted_mdns_request () {
|
||||
uint16 transaction_id = 0;
|
||||
uint16 flags = 0;
|
||||
uint16 num_questions = 1;
|
||||
uint16 answer_rrs = 0;
|
||||
uint16 authority_rrs = 0;
|
||||
uint16 additional_rrs = 0;
|
||||
string components[] = { "_remoted", "_tcp", "local" };
|
||||
uint16 record_type = 12;
|
||||
uint16 dns_class = 1;
|
||||
return new BufferBuilder (BIG_ENDIAN)
|
||||
.append_uint16 (transaction_id)
|
||||
.append_uint16 (flags)
|
||||
.append_uint16 (num_questions)
|
||||
.append_uint16 (answer_rrs)
|
||||
.append_uint16 (authority_rrs)
|
||||
.append_uint16 (additional_rrs)
|
||||
.append_uint8 ((uint8) components[0].length)
|
||||
.append_string (components[0], StringTerminator.NONE)
|
||||
.append_uint8 ((uint8) components[1].length)
|
||||
.append_string (components[1], StringTerminator.NONE)
|
||||
.append_uint8 ((uint8) components[2].length)
|
||||
.append_string (components[2], StringTerminator.NUL)
|
||||
.append_uint16 (record_type)
|
||||
.append_uint16 (dns_class)
|
||||
.build ();
|
||||
}
|
||||
|
||||
private class NcmPeer {
|
||||
public string address;
|
||||
|
||||
public class NcmPeer (string address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public async IOStream open_tcp_connection (uint16 port, Cancellable? cancellable) throws Error, IOError {
|
||||
SocketConnection connection;
|
||||
try {
|
||||
NetworkAddress service_address = NetworkAddress.parse (address, port);
|
||||
|
||||
var client = new SocketClient ();
|
||||
connection = yield client.connect_async (service_address, cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.TRANSPORT ("%s", e.message);
|
||||
}
|
||||
|
||||
Tcp.enable_nodelay (connection.socket);
|
||||
|
||||
return connection;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class LinuxTunnel : Object, Tunnel {
|
||||
public DiscoveryService discovery {
|
||||
get {
|
||||
return _discovery;
|
||||
}
|
||||
}
|
||||
|
||||
private TunnelConnection tunnel_connection;
|
||||
private DiscoveryService _discovery;
|
||||
|
||||
public LinuxTunnel (TunnelConnection conn, DiscoveryService disco) {
|
||||
tunnel_connection = conn;
|
||||
_discovery = disco;
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
tunnel_connection.cancel ();
|
||||
}
|
||||
|
||||
public async IOStream open_tcp_connection (uint16 port, Cancellable? cancellable) throws Error, IOError {
|
||||
return yield tunnel_connection.open_connection (port, cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
public class LinuxFruitFinder : Object, FruitFinder {
|
||||
public string? udid_from_iface (string ifname) throws Error {
|
||||
var net = "/sys/class/net";
|
||||
|
||||
var directory = File.new_build_filename (net, ifname);
|
||||
if (!directory.query_exists ())
|
||||
return null;
|
||||
|
||||
try {
|
||||
var info = directory.query_info ("standard::*", 0);
|
||||
if (!info.get_is_symlink ())
|
||||
return null;
|
||||
var dev_path = Path.build_filename (net, info.get_symlink_target ());
|
||||
|
||||
var iface = File.new_build_filename (dev_path, "..", "..", "interface");
|
||||
if (!iface.query_exists ())
|
||||
return null;
|
||||
var iface_stream = new DataInputStream (iface.read ());
|
||||
string iface_name = iface_stream.read_line ();
|
||||
if (iface_name != "NCM Control" && iface_name != "AppleUSBEthernet")
|
||||
return null;
|
||||
|
||||
var serial = File.new_build_filename (dev_path, "..", "..", "..", "serial");
|
||||
if (!serial.query_exists ())
|
||||
return null;
|
||||
|
||||
var serial_stream = new DataInputStream (serial.read ());
|
||||
return serial_stream.read_line ();
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.NOT_SUPPORTED ("%s", e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class LinuxPairingBrowser : Object, PairingBrowser {
|
||||
private DBusConnection connection;
|
||||
private AvahiServer server;
|
||||
private AvahiServiceBrowser browser;
|
||||
|
||||
private Gee.List<PairingServiceDetails> current_batch = new Gee.ArrayList<PairingServiceDetails> ();
|
||||
|
||||
private Cancellable io_cancellable = new Cancellable ();
|
||||
|
||||
construct {
|
||||
start.begin ();
|
||||
}
|
||||
|
||||
private async void start () {
|
||||
try {
|
||||
connection = yield GLib.Bus.get (BusType.SYSTEM, io_cancellable);
|
||||
|
||||
server = yield connection.get_proxy (AVAHI_SERVICE_NAME, "/", DO_NOT_LOAD_PROPERTIES, io_cancellable);
|
||||
|
||||
GLib.ObjectPath browser_path = yield server.service_browser_prepare (-1, INET6, PAIRING_REGTYPE,
|
||||
PAIRING_DOMAIN, 0, io_cancellable);
|
||||
browser = yield connection.get_proxy (AVAHI_SERVICE_NAME, browser_path, DO_NOT_LOAD_PROPERTIES,
|
||||
io_cancellable);
|
||||
browser.item_new.connect (on_item_new);
|
||||
browser.all_for_now.connect (on_all_for_now);
|
||||
yield browser.start (io_cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
printerr ("Oopsie: %s\n", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
private void on_item_new (int interface_index, AvahiProtocol protocol, string name, string type, string domain, uint flags) {
|
||||
char raw_interface_name[Linux.Network.INTERFACE_NAME_SIZE];
|
||||
Linux.Network.if_indextoname (interface_index, (string) raw_interface_name);
|
||||
unowned string interface_name = (string) raw_interface_name;
|
||||
current_batch.add (new LinuxPairingServiceDetails (name, interface_index, interface_name, protocol, server));
|
||||
}
|
||||
|
||||
private void on_all_for_now () {
|
||||
services_discovered (current_batch.to_array ());
|
||||
current_batch.clear ();
|
||||
}
|
||||
}
|
||||
|
||||
private class LinuxPairingServiceDetails : Object, PairingServiceDetails {
|
||||
public string name {
|
||||
get { return _name; }
|
||||
}
|
||||
|
||||
public uint interface_index {
|
||||
get { return _interface_index; }
|
||||
}
|
||||
|
||||
public string interface_name {
|
||||
get { return _interface_name; }
|
||||
}
|
||||
|
||||
private string _name;
|
||||
private uint _interface_index;
|
||||
private string _interface_name;
|
||||
private AvahiProtocol protocol;
|
||||
|
||||
private AvahiServer server;
|
||||
|
||||
internal LinuxPairingServiceDetails (string name, uint interface_index, string interface_name, AvahiProtocol protocol,
|
||||
AvahiServer server) {
|
||||
_name = name;
|
||||
_interface_index = interface_index;
|
||||
_interface_name = interface_name;
|
||||
this.protocol = protocol;
|
||||
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public async Gee.List<PairingServiceHost> resolve (Cancellable? cancellable) throws Error, IOError {
|
||||
AvahiServiceResolver resolver;
|
||||
try {
|
||||
GLib.ObjectPath path = yield server.service_resolver_prepare ((int) interface_index, protocol, name,
|
||||
PAIRING_REGTYPE, PAIRING_DOMAIN, INET6, 0, cancellable);
|
||||
DBusConnection connection = ((DBusProxy) server).get_connection ();
|
||||
resolver = yield connection.get_proxy (AVAHI_SERVICE_NAME, path, DO_NOT_LOAD_PROPERTIES, cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.NOT_SUPPORTED ("%s", e.message);
|
||||
}
|
||||
|
||||
var promise = new Promise<Gee.List<PairingServiceHost>> ();
|
||||
var hosts = new Gee.ArrayList<PairingServiceHost> ();
|
||||
resolver.found.connect ((interface_index, protocol, name, type, domain, host, address_protocol, address, port, txt,
|
||||
flags) => {
|
||||
var txt_record = new Gee.ArrayList<string> ();
|
||||
var iter = new VariantIter (txt);
|
||||
Variant? cur;
|
||||
while ((cur = iter.next_value ()) != null) {
|
||||
unowned string raw_val = (string) cur.get_data ();
|
||||
string val = raw_val.make_valid ((ssize_t) cur.get_size ());
|
||||
txt_record.add (val);
|
||||
}
|
||||
|
||||
hosts.add (new LinuxPairingServiceHost (
|
||||
host,
|
||||
new InetSocketAddress.from_string (address, port),
|
||||
port,
|
||||
txt_record));
|
||||
|
||||
if (!promise.future.ready)
|
||||
promise.resolve (hosts);
|
||||
});
|
||||
resolver.failure.connect (error => {
|
||||
if (!promise.future.ready)
|
||||
promise.reject (new Error.NOT_SUPPORTED ("%s", error));
|
||||
});
|
||||
|
||||
try {
|
||||
yield resolver.start (cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.NOT_SUPPORTED ("%s", e.message);
|
||||
}
|
||||
|
||||
return yield promise.future.wait_async (cancellable);
|
||||
}
|
||||
}
|
||||
|
||||
public class LinuxPairingServiceHost : Object, PairingServiceHost {
|
||||
public string name {
|
||||
get { return _name; }
|
||||
}
|
||||
|
||||
public InetSocketAddress address {
|
||||
get { return _address; }
|
||||
}
|
||||
|
||||
public uint16 port {
|
||||
get { return _port; }
|
||||
}
|
||||
|
||||
public Gee.List<string> txt_record {
|
||||
get { return _txt_record; }
|
||||
}
|
||||
|
||||
private string _name;
|
||||
private InetSocketAddress _address;
|
||||
private uint16 _port;
|
||||
private Gee.List<string> _txt_record;
|
||||
|
||||
internal LinuxPairingServiceHost (string name, InetSocketAddress address, uint16 port, Gee.List<string> txt_record) {
|
||||
_name = name;
|
||||
_address = address;
|
||||
_port = port;
|
||||
_txt_record = txt_record;
|
||||
}
|
||||
|
||||
public async Gee.List<InetSocketAddress> resolve (Cancellable? cancellable) throws Error, IOError {
|
||||
var result = new Gee.ArrayList<InetSocketAddress> ();
|
||||
result.add (address);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private const string AVAHI_SERVICE_NAME = "org.freedesktop.Avahi";
|
||||
|
||||
[DBus (name = "org.freedesktop.Avahi.Server2")]
|
||||
private interface AvahiServer : Object {
|
||||
public abstract async GLib.ObjectPath service_browser_prepare (int interface_index, AvahiProtocol protocol, string type,
|
||||
string domain, uint flags, Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async GLib.ObjectPath service_resolver_prepare (int interface_index, AvahiProtocol protocol, string name,
|
||||
string type, string domain, AvahiProtocol aprotocol, AvahiLookupFlags flags, Cancellable? cancellable)
|
||||
throws GLib.Error;
|
||||
}
|
||||
|
||||
[DBus (name = "org.freedesktop.Avahi.ServiceBrowser")]
|
||||
private interface AvahiServiceBrowser : Object {
|
||||
public signal void item_new (int interface_index, AvahiProtocol protocol, string name, string type, string domain,
|
||||
uint flags);
|
||||
public signal void item_remove (int interface_index, AvahiProtocol protocol, string name, string type, string domain,
|
||||
uint flags);
|
||||
public signal void failure (string error);
|
||||
public signal void all_for_now ();
|
||||
public signal void cache_exhausted ();
|
||||
|
||||
public abstract async void start (Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async void free (Cancellable? cancellable) throws GLib.Error;
|
||||
}
|
||||
|
||||
[DBus (name = "org.freedesktop.Avahi.ServiceResolver")]
|
||||
private interface AvahiServiceResolver : Object {
|
||||
public signal void found (int interface_index, AvahiProtocol protocol, string name, string type, string domain, string host,
|
||||
AvahiProtocol address_protocol, string address, uint16 port, [DBus (signature = "aay")] Variant txt, uint flags);
|
||||
public signal void failure (string error);
|
||||
|
||||
public abstract async void start (Cancellable? cancellable) throws GLib.Error;
|
||||
public abstract async void free (Cancellable? cancellable) throws GLib.Error;
|
||||
}
|
||||
|
||||
private enum AvahiProtocol {
|
||||
INET,
|
||||
INET6,
|
||||
UNSPEC = -1,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum AvahiLookupFlags {
|
||||
USE_WIDE_AREA = 1,
|
||||
USE_MULTICAST = 2,
|
||||
NO_TXT = 4,
|
||||
NO_ADDRESS = 8,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,420 @@
|
||||
[CCode (gir_namespace = "FridaFruity", gir_version = "1.0")]
|
||||
namespace Frida.Fruity {
|
||||
using Darwin.GCD;
|
||||
using Darwin.IOKit;
|
||||
|
||||
public sealed class MacOSTunnelFinder : Object, TunnelFinder {
|
||||
public async Tunnel? find (string udid, Cancellable? cancellable) throws Error, IOError {
|
||||
var main_context = MainContext.ref_thread_default ();
|
||||
var event_queue = new DispatchQueue ("re.frida.fruity.tunnel", DispatchQueueAttr.SERIAL);
|
||||
|
||||
Darwin.Xpc.Dictionary? device_info = null;
|
||||
bool all_listed = false;
|
||||
bool waiting = false;
|
||||
|
||||
var pairingd = XpcClient.make_for_mach_service ("com.apple.CoreDevice.remotepairingd", event_queue);
|
||||
pairingd.notify["state"].connect ((obj, pspec) => {
|
||||
if (waiting)
|
||||
find.callback ();
|
||||
});
|
||||
pairingd.message.connect (obj => {
|
||||
var reader = new XpcObjectReader (obj);
|
||||
|
||||
try {
|
||||
reader.read_member ("mangledTypeName");
|
||||
if (reader.get_string_value () == "RemotePairing.ServiceEvent") {
|
||||
reader
|
||||
.end_member ()
|
||||
.read_member ("value");
|
||||
if (reader.try_read_member ("deviceFound")) {
|
||||
reader
|
||||
.read_member ("_0")
|
||||
.read_member ("deviceInfo")
|
||||
.read_member ("udid");
|
||||
if (reader.get_string_value () == udid) {
|
||||
reader.end_member ();
|
||||
device_info = (Darwin.Xpc.Dictionary) reader.current_object;
|
||||
}
|
||||
} else if (reader.has_member ("allCurrentDevicesListed")) {
|
||||
all_listed = true;
|
||||
}
|
||||
}
|
||||
} catch (Error e) {
|
||||
}
|
||||
|
||||
var source = new IdleSource ();
|
||||
source.set_callback (() => {
|
||||
if (waiting)
|
||||
find.callback ();
|
||||
return Source.REMOVE;
|
||||
});
|
||||
source.attach (main_context);
|
||||
});
|
||||
|
||||
var r = new PairingdRequest ("RemotePairing.BrowseRequest");
|
||||
r.body.set_bool ("currentDevicesOnly", true);
|
||||
yield pairingd.request (r.message, cancellable);
|
||||
|
||||
while (!all_listed && pairingd.state == OPEN) {
|
||||
waiting = true;
|
||||
yield;
|
||||
waiting = false;
|
||||
}
|
||||
|
||||
if (device_info == null) {
|
||||
if (all_listed)
|
||||
throw new Error.INVALID_ARGUMENT ("Device not found");
|
||||
else
|
||||
throw new Error.NOT_SUPPORTED ("Unexpectedly lost connection to remotepairingd");
|
||||
}
|
||||
|
||||
var pairing_device = new XpcClient (device_info.create_connection ("endpoint"), event_queue);
|
||||
var tunnel = new MacOSTunnel (pairing_device);
|
||||
yield tunnel.attach (cancellable);
|
||||
return tunnel;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class MacOSTunnel : Object, Tunnel {
|
||||
public DiscoveryService discovery {
|
||||
get {
|
||||
return _discovery;
|
||||
}
|
||||
}
|
||||
|
||||
private XpcClient pairing_device;
|
||||
private Darwin.Xpc.Object? assertion_identifier;
|
||||
private InetAddress? tunnel_device_address;
|
||||
private DiscoveryService? _discovery;
|
||||
|
||||
public MacOSTunnel (XpcClient pairing_device) {
|
||||
this.pairing_device = pairing_device;
|
||||
}
|
||||
|
||||
public async void close (Cancellable? cancellable) throws IOError {
|
||||
var r = new PairingdRequest ("RemotePairing.ReleaseAssertionRequest");
|
||||
r.body.set_value ("assertionIdentifier", assertion_identifier);
|
||||
try {
|
||||
yield pairing_device.request (r.message, cancellable);
|
||||
} catch (Error e) {
|
||||
}
|
||||
}
|
||||
|
||||
public async void attach (Cancellable? cancellable) throws Error, IOError {
|
||||
var r = new PairingdRequest ("RemotePairing.CreateAssertionCommand");
|
||||
r.body.set_int64 ("flags", 0);
|
||||
var response = yield pairing_device.request (r.message, cancellable);
|
||||
|
||||
var reader = new XpcObjectReader (response);
|
||||
reader.read_member ("response");
|
||||
|
||||
assertion_identifier = reader
|
||||
.read_member ("assertionIdentifier")
|
||||
.get_object_value (Darwin.Xpc.Uuid.TYPE);
|
||||
reader.end_member ();
|
||||
|
||||
string tunnel_ip_address = reader
|
||||
.read_member ("info")
|
||||
.read_member ("tunnelIPAddress")
|
||||
.get_string_value ();
|
||||
tunnel_device_address = new InetAddress.from_string (tunnel_ip_address);
|
||||
|
||||
_discovery = yield locate_discovery_service (tunnel_device_address, cancellable);
|
||||
}
|
||||
|
||||
public async IOStream open_tcp_connection (uint16 port, Cancellable? cancellable) throws Error, IOError {
|
||||
SocketConnection connection;
|
||||
try {
|
||||
var service_address = new InetSocketAddress (tunnel_device_address, port);
|
||||
|
||||
var client = new SocketClient ();
|
||||
connection = yield client.connect_async (service_address, cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
throw new Error.TRANSPORT ("%s", e.message);
|
||||
}
|
||||
|
||||
Tcp.enable_nodelay (connection.socket);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
private static async DiscoveryService locate_discovery_service (InetAddress tunnel_device_address, Cancellable? cancellable)
|
||||
throws Error, IOError {
|
||||
var path_buf = new char[4096];
|
||||
unowned string path = (string) path_buf;
|
||||
|
||||
foreach (var item in XNU.query_active_tcp_connections ()) {
|
||||
if (item.family != IPV6)
|
||||
continue;
|
||||
if (!item.foreign_address.equal (tunnel_device_address))
|
||||
continue;
|
||||
if (Darwin.XNU.proc_pidpath (item.effective_pid, path_buf) <= 0)
|
||||
continue;
|
||||
if (path != "/usr/libexec/remoted")
|
||||
continue;
|
||||
|
||||
try {
|
||||
var connectable = new InetSocketAddress (tunnel_device_address, item.foreign_port);
|
||||
|
||||
var sc = new SocketClient ();
|
||||
SocketConnection connection = yield sc.connect_async (connectable, cancellable);
|
||||
Tcp.enable_nodelay (connection.socket);
|
||||
|
||||
return yield DiscoveryService.open (connection, cancellable);
|
||||
} catch (GLib.Error e) {
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error.NOT_SUPPORTED ("Unable to detect RSD port");
|
||||
}
|
||||
}
|
||||
|
||||
private class PairingdRequest {
|
||||
public Darwin.Xpc.Dictionary message = new Darwin.Xpc.Dictionary ();
|
||||
public Darwin.Xpc.Dictionary body = new Darwin.Xpc.Dictionary ();
|
||||
|
||||
public PairingdRequest (string name) {
|
||||
message.set_string ("mangledTypeName", name);
|
||||
message.set_value ("value", body);
|
||||
}
|
||||
}
|
||||
|
||||
public class MacOSFruitFinder : Object, FruitFinder {
|
||||
public string? udid_from_iface (string ifname) throws Error {
|
||||
var matching_dict = Darwin.IOKit.service_matching (Darwin.IOKit.ETHERNET_INTERFACE_CLASS);
|
||||
if (matching_dict == null)
|
||||
return null;
|
||||
matching_dict.add (CoreFoundation.String.make (Darwin.IOKit.BSD_NAME_KEY), CoreFoundation.String.make (ifname));
|
||||
|
||||
var registry = IORegistry.open ();
|
||||
foreach (var service in registry.matching_services (matching_dict)) {
|
||||
var usb_serial = find_idevice (service.parent (Darwin.IOKit.IOSERVICE_PLANE));
|
||||
if (usb_serial != null)
|
||||
return usb_serial;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? find_idevice (IORegistryEntry service) throws Error {
|
||||
if (service.get_string_property ("CFBundleIdentifier") == "com.apple.driver.usb.cdc.ncm")
|
||||
return find_idevice (service.parent (Darwin.IOKit.IOSERVICE_PLANE));
|
||||
|
||||
var props = service.get_properties ();
|
||||
|
||||
var prod = props.get_string_value ("USB Product Name");
|
||||
if (prod != "iPhone" && prod != "iPad")
|
||||
return null;
|
||||
|
||||
return props.get_string_value ("USB Serial Number");
|
||||
}
|
||||
}
|
||||
|
||||
namespace XNU {
|
||||
public PcbList query_active_tcp_connections () {
|
||||
size_t size = 0;
|
||||
Darwin.XNU.sysctlbyname ("net.inet.tcp.pcblist_n", null, &size);
|
||||
|
||||
var pcbs = new uint8[size];
|
||||
Darwin.XNU.sysctlbyname ("net.inet.tcp.pcblist_n", pcbs, &size);
|
||||
|
||||
return new PcbList (pcbs);
|
||||
}
|
||||
|
||||
public class PcbList {
|
||||
private uint8[] pcbs;
|
||||
|
||||
internal PcbList (owned uint8[] pcbs) {
|
||||
this.pcbs = (owned) pcbs;
|
||||
}
|
||||
|
||||
public Iterator iterator () {
|
||||
return new Iterator (this);
|
||||
}
|
||||
|
||||
public class Iterator {
|
||||
private PcbList list;
|
||||
private InetItem * cursor;
|
||||
|
||||
internal Iterator (PcbList list) {
|
||||
this.list = list;
|
||||
|
||||
var gen = (Darwin.XNU.InetPcbGeneration *) list.pcbs;
|
||||
cursor = (InetItem *) ((uint8 *) list.pcbs + gen->length);
|
||||
}
|
||||
|
||||
public Item? next_value () {
|
||||
InetPcb * pcb = null;
|
||||
while (true) {
|
||||
if (cursor->length == 24)
|
||||
return null;
|
||||
|
||||
switch (cursor->kind) {
|
||||
case InetItemKind.PCB:
|
||||
pcb = (InetPcb *) cursor;
|
||||
break;
|
||||
case InetItemKind.SOCKET:
|
||||
var item = new Item (*pcb, *((InetSocket *) cursor));
|
||||
advance ();
|
||||
return item;
|
||||
}
|
||||
|
||||
advance ();
|
||||
}
|
||||
}
|
||||
|
||||
private void advance () {
|
||||
uint32 l = cursor->length;
|
||||
if (l % 8 != 0)
|
||||
l += 8 - (l % 8);
|
||||
cursor = (InetItem *) ((uint8 *) cursor + l);
|
||||
}
|
||||
}
|
||||
|
||||
public class Item {
|
||||
public SocketFamily family {
|
||||
get {
|
||||
return ((pcb.version_flag & Darwin.XNU.InetVersionFlags.IPV6) != 0)
|
||||
? SocketFamily.IPV6
|
||||
: SocketFamily.IPV4;
|
||||
}
|
||||
}
|
||||
|
||||
public InetAddress local_address {
|
||||
get {
|
||||
if (cached_local_address == null)
|
||||
cached_local_address = parse_address (pcb.local_address);
|
||||
return cached_local_address;
|
||||
}
|
||||
}
|
||||
|
||||
public uint16 local_port {
|
||||
get {
|
||||
return uint16.from_big_endian (pcb.local_port);
|
||||
}
|
||||
}
|
||||
|
||||
public InetAddress foreign_address {
|
||||
get {
|
||||
if (cached_foreign_address == null)
|
||||
cached_foreign_address = parse_address (pcb.foreign_address);
|
||||
return cached_foreign_address;
|
||||
}
|
||||
}
|
||||
|
||||
public uint16 foreign_port {
|
||||
get {
|
||||
return uint16.from_big_endian (pcb.foreign_port);
|
||||
}
|
||||
}
|
||||
|
||||
public int32 effective_pid {
|
||||
get {
|
||||
return sock.effective_pid;
|
||||
}
|
||||
}
|
||||
|
||||
private InetPcb pcb;
|
||||
private InetSocket sock;
|
||||
private InetAddress? cached_local_address;
|
||||
private InetAddress? cached_foreign_address;
|
||||
|
||||
public Item (InetPcb pcb, InetSocket sock) {
|
||||
this.pcb = pcb;
|
||||
this.sock = sock;
|
||||
}
|
||||
|
||||
private InetAddress parse_address (uint8[] bytes) {
|
||||
if ((pcb.version_flag & Darwin.XNU.InetVersionFlags.IPV6) != 0)
|
||||
return new InetAddress.from_bytes (bytes, IPV6);
|
||||
var addr = (Darwin.XNU.InetAddr4in6 *) bytes;
|
||||
return new InetAddress.from_bytes ((uint8[]) &addr->addr4.s_addr, IPV4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SimpleType]
|
||||
public struct InetItem {
|
||||
public uint32 length;
|
||||
public uint32 kind;
|
||||
}
|
||||
|
||||
public enum InetItemKind {
|
||||
SOCKET = 0x001,
|
||||
PCB = 0x010,
|
||||
}
|
||||
|
||||
[SimpleType]
|
||||
public struct InetPcb {
|
||||
public uint32 length;
|
||||
public uint32 kind;
|
||||
|
||||
public uint64 inpp;
|
||||
public uint16 foreign_port;
|
||||
public uint16 local_port;
|
||||
public uint32 per_protocol_pcb_low;
|
||||
public uint32 per_protocol_pcb_high;
|
||||
public uint32 generation_count_low;
|
||||
public uint32 generation_count_high;
|
||||
public int flags;
|
||||
public uint32 flow;
|
||||
public uint8 version_flag;
|
||||
public uint8 ip_ttl;
|
||||
public uint8 ip_protocol;
|
||||
public uint8 padding;
|
||||
public uint8 foreign_address[16];
|
||||
public uint8 local_address[16];
|
||||
public InetDepend4 depend4;
|
||||
public InetDepend6 depend6;
|
||||
public uint32 flowhash;
|
||||
public uint32 flags2;
|
||||
}
|
||||
|
||||
[SimpleType]
|
||||
public struct InetSocket {
|
||||
public uint32 length;
|
||||
public uint32 kind;
|
||||
|
||||
public uint64 so;
|
||||
public int16 type;
|
||||
public uint16 options_low;
|
||||
public uint16 options_high;
|
||||
public int16 linger;
|
||||
public int16 state;
|
||||
public uint16 pcb[4];
|
||||
public uint16 protocol_low;
|
||||
public uint16 protocol_high;
|
||||
public uint16 family_low;
|
||||
public uint16 family_high;
|
||||
public int16 qlen;
|
||||
public int16 incqlen;
|
||||
public int16 qlimit;
|
||||
public int16 timeo;
|
||||
public uint16 error;
|
||||
public int32 pgid;
|
||||
public uint32 oobmark;
|
||||
public uint32 uid;
|
||||
public int32 last_pid;
|
||||
public int32 effective_pid;
|
||||
public uint64 gencnt;
|
||||
public uint32 flags;
|
||||
public uint32 flags1;
|
||||
public int32 usecount;
|
||||
public int32 retaincnt;
|
||||
public uint32 filter_flags;
|
||||
}
|
||||
|
||||
[SimpleType]
|
||||
public struct InetDepend4 {
|
||||
public uint8 ip_tos;
|
||||
}
|
||||
|
||||
[SimpleType]
|
||||
public struct InetDepend6 {
|
||||
public uint8 hlim;
|
||||
public int checksum;
|
||||
public uint16 interface_index;
|
||||
public int16 hops;
|
||||
}
|
||||
}
|
||||
}
|
||||
+4419
File diff suppressed because it is too large.
Load diff
@@ -177,12 +177,16 @@ namespace Frida {
|
||||
}
|
||||
}
|
||||
|
||||
public interface ChannelProvider : Object {
|
||||
public interface HostChannelProvider : Object {
|
||||
public abstract async IOStream open_channel (string address, Cancellable? cancellable = null) throws Error, IOError;
|
||||
}
|
||||
|
||||
public interface HostServiceProvider : Object {
|
||||
public abstract async Service open_service (string address, Cancellable? cancellable = null) throws Error, IOError;
|
||||
}
|
||||
|
||||
public interface Pairable : Object {
|
||||
public abstract async void unpair (Cancellable? cancellable) throws Error, IOError;
|
||||
public abstract async void unpair (Cancellable? cancellable = null) throws Error, IOError;
|
||||
}
|
||||
|
||||
public interface HostSessionBackend : Object {
|
||||
@@ -1537,7 +1541,7 @@ namespace Frida {
|
||||
|
||||
#if HAVE_FRUITY_BACKEND || HAVE_DROIDY_BACKEND
|
||||
internal async DBusConnection establish_direct_connection (TransportBroker broker, AgentSessionId id,
|
||||
ChannelProvider channel_provider, Cancellable? cancellable) throws Error, IOError {
|
||||
HostChannelProvider channel_provider, Cancellable? cancellable) throws Error, IOError {
|
||||
uint16 port;
|
||||
string token;
|
||||
try {
|
||||
|
||||
+40
-2
@@ -470,8 +470,8 @@ if have_local_backend
|
||||
agent_legacy,
|
||||
agent_emulated_modern,
|
||||
agent_emulated_legacy,
|
||||
get_option('agent_dbghelp_prefix'),
|
||||
get_option('agent_symsrv_prefix'),
|
||||
gum_dep.get_variable('frida_dbghelp_prefix'),
|
||||
gum_dep.get_variable('frida_symsrv_prefix'),
|
||||
],
|
||||
depends: agent_depends,
|
||||
)
|
||||
@@ -481,6 +481,7 @@ endif
|
||||
if have_fruity_backend
|
||||
backend_sources += [
|
||||
'fruity' / 'fruity-host-session.vala',
|
||||
'fruity' / 'xpc.vala',
|
||||
'fruity' / 'dtx.vala',
|
||||
'fruity' / 'lockdown.vala',
|
||||
'fruity' / 'installation-proxy.vala',
|
||||
@@ -492,6 +493,7 @@ if have_fruity_backend
|
||||
'fruity' / 'plist.vala',
|
||||
'fruity' / 'plist-service.vala',
|
||||
]
|
||||
|
||||
if host_os_family == 'windows'
|
||||
backend_sources += 'fruity' / 'fruity-host-session-windows.c'
|
||||
elif host_os_family == 'darwin'
|
||||
@@ -499,6 +501,41 @@ if have_fruity_backend
|
||||
else
|
||||
backend_sources += 'fruity' / 'fruity-host-session-unix.c'
|
||||
endif
|
||||
|
||||
if host_os_family == 'darwin'
|
||||
backend_sources += 'fruity' / 'xpc-darwin.vala'
|
||||
endif
|
||||
if host_os == 'macos'
|
||||
backend_sources += [
|
||||
'fruity' / 'xpc-macos.vala',
|
||||
'fruity' / 'iokit.vala',
|
||||
]
|
||||
elif host_os == 'linux'
|
||||
backend_sources += 'fruity' / 'xpc-linux.vala'
|
||||
endif
|
||||
|
||||
backend_deps += openssl_dep
|
||||
backend_vala_args += [
|
||||
'--pkg=libnghttp2',
|
||||
'--pkg=libngtcp2',
|
||||
'--pkg=libngtcp2_crypto_quictls',
|
||||
'--pkg=lwip',
|
||||
'--pkg=openssl',
|
||||
]
|
||||
if host_os_family == 'darwin'
|
||||
backend_vala_args += [
|
||||
'--pkg=darwin-xnu',
|
||||
'--pkg=darwin-iokit',
|
||||
'--pkg=darwin-xpc',
|
||||
'--pkg=darwin-gcd',
|
||||
'--pkg=darwin-net',
|
||||
'--pkg=darwin-dns-sd',
|
||||
'--pkg=corefoundation',
|
||||
]
|
||||
endif
|
||||
if host_os_family == 'linux'
|
||||
backend_vala_args += '--pkg=linux'
|
||||
endif
|
||||
endif
|
||||
|
||||
if have_droidy_backend
|
||||
@@ -556,6 +593,7 @@ core_deps += backend_deps_private
|
||||
|
||||
core_vala_args = [
|
||||
backend_vala_args,
|
||||
base_vala_args,
|
||||
'--pkg=gio-2.0',
|
||||
gio_platform_vala_args,
|
||||
'--pkg=json-glib-1.0',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/frida/frida-gum.git
|
||||
revision = 16.2.2
|
||||
revision = 16.3.2
|
||||
depth = 1
|
||||
|
||||
[provide]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/frida/libnice.git
|
||||
revision = a0f43f0ea5755ce0374613b0a157be33a9f7d82e
|
||||
revision = e12567b0a16a0c2eb5dfe5e0782baba8496772ff
|
||||
depth = 1
|
||||
|
||||
[provide]
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/frida/lwip.git
|
||||
revision = 9f64c40cac2e77eddf6b3913961fdd056d307716
|
||||
depth = 1
|
||||
|
||||
[provide]
|
||||
dependency_names = lwip
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/frida/ngtcp2.git
|
||||
revision = cc5cf523615b7fa7a9340234c7eec3c3645ae969
|
||||
depth = 1
|
||||
|
||||
[provide]
|
||||
dependency_names = libngtcp2, libngtcp2_crypto_quictls
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[wrap-git]
|
||||
url = https://github.com/frida/openssl.git
|
||||
revision = 95d037b2acc432039da4f506d25b6a01577d8bc5
|
||||
revision = ca4781aaf7910b623d3ae21c6a017e7e9ca6936c
|
||||
depth = 1
|
||||
|
||||
[provide]
|
||||
|
||||
@@ -60,6 +60,11 @@ namespace Frida.HostSessionTest {
|
||||
var h = new Harness ((h) => Fruity.Manual.lockdown.begin (h as Harness));
|
||||
h.run ();
|
||||
});
|
||||
|
||||
GLib.Test.add_func ("/HostSession/Fruity/Manual/xpc", () => {
|
||||
var h = new Harness ((h) => Fruity.Manual.xpc.begin (h as Harness));
|
||||
h.run ();
|
||||
});
|
||||
#endif
|
||||
|
||||
#if HAVE_DROIDY_BACKEND
|
||||
@@ -3517,16 +3522,17 @@ namespace Frida.HostSessionTest {
|
||||
#endif
|
||||
|
||||
Variant? icon = prov.icon;
|
||||
assert_nonnull (icon);
|
||||
var dict = new VariantDict (icon);
|
||||
int64 width, height;
|
||||
assert_true (dict.lookup ("width", "x", out width));
|
||||
assert_true (dict.lookup ("height", "x", out height));
|
||||
assert_true (width == 16);
|
||||
assert_true (height == 16);
|
||||
VariantIter image;
|
||||
assert_true (dict.lookup ("image", "ay", out image));
|
||||
assert_true (image.n_children () == width * height * 4);
|
||||
if (icon != null) {
|
||||
var dict = new VariantDict (icon);
|
||||
int64 width, height;
|
||||
assert_true (dict.lookup ("width", "x", out width));
|
||||
assert_true (dict.lookup ("height", "x", out height));
|
||||
assert_true (width == 16);
|
||||
assert_true (height == 16);
|
||||
VariantIter image;
|
||||
assert_true (dict.lookup ("image", "ay", out image));
|
||||
assert_true (image.n_children () == width * height * 4);
|
||||
}
|
||||
|
||||
try {
|
||||
Cancellable? cancellable = null;
|
||||
@@ -3741,6 +3747,41 @@ namespace Frida.HostSessionTest {
|
||||
h.done ();
|
||||
}
|
||||
|
||||
private static async void xpc (Harness h) {
|
||||
if (!GLib.Test.slow ()) {
|
||||
stdout.printf ("<skipping, run in slow mode with iOS device connected> ");
|
||||
h.done ();
|
||||
return;
|
||||
}
|
||||
|
||||
var device_id = "<device-id>";
|
||||
|
||||
var device_manager = new DeviceManager ();
|
||||
|
||||
try {
|
||||
var timer = new Timer ();
|
||||
var device = yield device_manager.get_device_by_id (device_id);
|
||||
printerr ("[*] Got device in %u ms\n", (uint) (timer.elapsed () * 1000.0));
|
||||
|
||||
timer.reset ();
|
||||
var appservice = yield device.open_service ("xpc:com.apple.coredevice.appservice");
|
||||
printerr ("[*] Opened service in %u ms\n", (uint) (timer.elapsed () * 1000.0));
|
||||
|
||||
var parameters = new HashTable<string, Variant> (str_hash, str_equal);
|
||||
parameters["CoreDevice.featureIdentifier"] = "com.apple.coredevice.feature.listprocesses";
|
||||
parameters["CoreDevice.action"] = new HashTable<string, Variant> (str_hash, str_equal);
|
||||
parameters["CoreDevice.input"] = new HashTable<string, Variant> (str_hash, str_equal);
|
||||
timer.reset ();
|
||||
var response = yield appservice.request (parameters);
|
||||
printerr ("[*] Made request in %u ms\n", (uint) (timer.elapsed () * 1000.0));
|
||||
printerr ("Got response: %s\n", response.print (true));
|
||||
} catch (GLib.Error e) {
|
||||
printerr ("\nFAIL: %s\n\n", e.message);
|
||||
}
|
||||
|
||||
h.done ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Plist {
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
[CCode (cheader_filename = "CoreFoundation/CFDictionary.h", gir_namespace = "Darwin", gir_version = "1.0")]
|
||||
namespace CoreFoundation {
|
||||
[Compact]
|
||||
[CCode (cname = "struct __CFDictionary", ref_function = "CFRetain", unref_function = "CFRelease")]
|
||||
public class Dictionary : Type {
|
||||
[CCode (cname = "CFDictionaryGetCount")]
|
||||
public Index count ();
|
||||
|
||||
[CCode (cname = "CFDictionaryGetValue")]
|
||||
public void * @get (void * key);
|
||||
|
||||
public string get_string_value (string key) {
|
||||
return ((String) @get (String.make (key))).to_string ();
|
||||
}
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "struct __CFDictionary", ref_function = "CFRetain", unref_function = "CFRelease")]
|
||||
public class MutableDictionary : Dictionary {
|
||||
[CCode (cname = "CFDictionaryRemoveAllValues")]
|
||||
public void clear ();
|
||||
|
||||
[CCode (cname = "CFDictionaryAddValue")]
|
||||
public void add (void * key, void * value);
|
||||
|
||||
[CCode (cname = "CFDictionaryRemoveValue")]
|
||||
public void remove (void * key);
|
||||
}
|
||||
|
||||
// TODO: Inherit CFTypeRef? CFStringRef vs __CFString
|
||||
[Compact]
|
||||
[CCode (cname = "const struct __CFString", ref_function = "CFRetain", unref_function = "CFRelease")]
|
||||
public class String : Type {
|
||||
public Index length {
|
||||
get { return _length (); }
|
||||
}
|
||||
|
||||
public static String make (string str) {
|
||||
return from_cstring (null, str, StringEncoding.UTF8);
|
||||
}
|
||||
|
||||
public string to_string () {
|
||||
var max_length = max_size_for_encoding (length, StringEncoding.UTF8) + 1;
|
||||
var buffer = new char[max_length];
|
||||
to_cstring (buffer, max_length, StringEncoding.UTF8);
|
||||
return (string) buffer;
|
||||
}
|
||||
|
||||
[CCode (cname = "CFStringCreateWithCString")]
|
||||
private static String from_cstring (Allocator? allocator, uint8 * c_str, StringEncoding encoding);
|
||||
|
||||
[CCode (cname = "CFStringGetCString")]
|
||||
private bool to_cstring (uint8 * buffer, Index buffer_size, StringEncoding encoding);
|
||||
|
||||
[CCode (cname = "CFStringGetLength")]
|
||||
private Index _length ();
|
||||
|
||||
[CCode (cname = "CFStringGetMaximumSizeForEncoding")]
|
||||
private static Index max_size_for_encoding (Index length, StringEncoding encoding);
|
||||
}
|
||||
|
||||
[CCode (cname = "CFStringEncoding", cprefix = "kCFStringEncoding", has_type_id = false)]
|
||||
public enum StringEncoding {
|
||||
MacRoman,
|
||||
WindowsLatin1,
|
||||
ISOLatin1,
|
||||
NextStepLatin,
|
||||
ASCII,
|
||||
Unicode,
|
||||
UTF8,
|
||||
NonLossyASCII,
|
||||
UTF16,
|
||||
UTF16BE,
|
||||
UTF16LE,
|
||||
UTF32,
|
||||
UTF32BE,
|
||||
UTF32LE,
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "const void", ref_function = "CFRetain", unref_function = "CFRelease")]
|
||||
public class Type {
|
||||
[CCode (cname = "CFShow")]
|
||||
public void show ();
|
||||
|
||||
public string to_string () {
|
||||
return description ().to_string ();
|
||||
}
|
||||
|
||||
[CCode (cname = "CFCopyDescription")]
|
||||
private String description ();
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "CFAllocatorRef")]
|
||||
public class Allocator {
|
||||
[CCode (cname = "CFAllocatorGetDefault")]
|
||||
public static Allocator get_default ();
|
||||
}
|
||||
|
||||
[CCode (cname = "CFIndex", has_type_id = false)]
|
||||
public struct Index : long {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
[CCode (cheader_filename = "dns_sd.h", gir_namespace = "Darwin", gir_version = "1.0")]
|
||||
namespace Darwin.DNSSD {
|
||||
[CCode (cname = "DNSServiceRef", ref_function = "", unref_function = "")]
|
||||
public class DNSService {
|
||||
[CCode (cname = "DNSServiceCreateConnection")]
|
||||
public static ErrorType create_connection (out DNSService service);
|
||||
|
||||
[CCode (cname = "DNSServiceRefDeallocate")]
|
||||
public void deallocate ();
|
||||
|
||||
[CCode (cname = "DNSServiceSetDispatchQueue")]
|
||||
public ErrorType set_dispatch_queue (Darwin.GCD.DispatchQueue queue);
|
||||
|
||||
[CCode (cname = "DNSServiceBrowse")]
|
||||
public static ErrorType browse (ref DNSService sd_ref, Flags flags, uint32 interface_index, string regtype, string? domain,
|
||||
BrowseReply callback);
|
||||
|
||||
[CCode (cname = "DNSServiceResolve")]
|
||||
public static ErrorType resolve (ref DNSService sd_ref, Flags flags, uint32 interface_index, string name, string regtype,
|
||||
string domain, ResolveReply callback);
|
||||
|
||||
[CCode (cname = "DNSServiceGetAddrInfo")]
|
||||
public static ErrorType get_addr_info (ref DNSService sd_ref, Flags flags, uint32 interface_index, Protocol protocol,
|
||||
string hostname, GetAddrInfoReply callback);
|
||||
|
||||
[CCode (cname = "DNSServiceBrowseReply")]
|
||||
public delegate void BrowseReply (DNSService sd_ref, Flags flags, uint32 interface_index, ErrorType error_code,
|
||||
string service_name, string regtype, string reply_domain);
|
||||
|
||||
[CCode (cname = "DNSServiceResolveReply")]
|
||||
public delegate void ResolveReply (DNSService sd_ref, Flags flags, uint32 interface_index, ErrorType error_code,
|
||||
string fullname, string hosttarget, uint16 port, [CCode (array_length_pos = 7.9, array_length_type = "uint16_t")] uint8[] txt_record);
|
||||
|
||||
[CCode (cname = "DNSServiceGetAddrInfoReply")]
|
||||
public delegate void GetAddrInfoReply (DNSService sd_ref, Flags flags, uint32 interface_index, ErrorType error_code,
|
||||
string hostname, void * address, uint32 ttl);
|
||||
|
||||
[CCode (cname = "DNSServiceErrorType", cprefix = "kDNSServiceErr_", has_type_id = false)]
|
||||
public enum ErrorType {
|
||||
NoError,
|
||||
Unknown,
|
||||
NoSuchName,
|
||||
NoMemory,
|
||||
BadParam,
|
||||
BadReference,
|
||||
BadState,
|
||||
BadFlags,
|
||||
Unsupported,
|
||||
NotInitialized,
|
||||
AlreadyRegistered,
|
||||
NameConflict,
|
||||
Invalid,
|
||||
Firewall,
|
||||
Incompatible,
|
||||
BadInterfaceIndex,
|
||||
Refused,
|
||||
NoSuchRecord,
|
||||
NoAuth,
|
||||
NoSuchKey,
|
||||
NATTraversal,
|
||||
DoubleNAT,
|
||||
BadTime,
|
||||
BadSig,
|
||||
BadKey,
|
||||
Transient,
|
||||
ServiceNotRunning,
|
||||
NATPortMappingUnsupported,
|
||||
NATPortMappingDisabled,
|
||||
NoRouter,
|
||||
PollingMode,
|
||||
Timeout,
|
||||
DefunctConnection,
|
||||
PolicyDenied,
|
||||
NotPermitted,
|
||||
}
|
||||
|
||||
[CCode (cname = "DNSServiceFlags", cprefix = "kDNSServiceFlags", has_type_id = false)]
|
||||
[Flags]
|
||||
public enum Flags {
|
||||
MoreComing,
|
||||
QueueRequest,
|
||||
AutoTrigger,
|
||||
Add,
|
||||
Default,
|
||||
NoAutoRename,
|
||||
Shared,
|
||||
Unique,
|
||||
BrowseDomains,
|
||||
RegistrationDomains,
|
||||
LongLivedQuery,
|
||||
AllowRemoteQuery,
|
||||
ForceMulticast,
|
||||
Force,
|
||||
KnownUnique,
|
||||
ReturnIntermediates,
|
||||
ShareConnection,
|
||||
SuppressUnusable,
|
||||
Timeout,
|
||||
IncludeP2P,
|
||||
WakeOnResolve,
|
||||
BackgroundTrafficClass,
|
||||
IncludeAWDL,
|
||||
EnableDNSSEC,
|
||||
Validate,
|
||||
Secure,
|
||||
Insecure,
|
||||
Bogus,
|
||||
Indeterminate,
|
||||
UnicastResponse,
|
||||
ValidateOptional,
|
||||
WakeOnlyService,
|
||||
ThresholdOne,
|
||||
ThresholdFinder,
|
||||
ThresholdReached,
|
||||
PrivateOne,
|
||||
PrivateTwo,
|
||||
PrivateThree,
|
||||
PrivateFour,
|
||||
PrivateFive,
|
||||
[CCode (cname = "kDNSServiceFlagAnsweredFromCache")]
|
||||
AnsweredFromCache,
|
||||
AllowExpiredAnswers,
|
||||
ExpiredAnswer,
|
||||
}
|
||||
|
||||
[CCode (cname = "DNSServiceProtocol", cprefix = "kDNSServiceProtocol_", has_type_id = false)]
|
||||
public enum Protocol {
|
||||
IPv4 = 0x01,
|
||||
IPv6 = 0x02,
|
||||
UDP = 0x10,
|
||||
TCP = 0x20,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
[CCode (cheader_filename = "dispatch/dispatch.h", gir_namespace = "Darwin", gir_version = "1.0")]
|
||||
namespace Darwin.GCD {
|
||||
[Compact]
|
||||
[CCode (cname = "void", ref_function = "_frida_dispatch_retain", unref_function = "dispatch_release",
|
||||
cheader_filename = "frida-darwin.h")]
|
||||
public class DispatchQueue {
|
||||
[CCode (cname = "dispatch_queue_create")]
|
||||
public DispatchQueue (string label, DispatchQueueAttr attr);
|
||||
|
||||
[CCode (cname = "dispatch_async_f")]
|
||||
public void dispatch_async ([CCode (delegate_target_pos = 0.9)] DispatchFunction work);
|
||||
|
||||
[CCode (cname = "dispatch_sync_f")]
|
||||
public void dispatch_sync ([CCode (delegate_target_pos = 0.9)] DispatchFunction work);
|
||||
}
|
||||
|
||||
[CCode (cname = "dispatch_function_t")]
|
||||
public delegate void DispatchFunction ();
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "dispatch_queue_attr_t", cprefix = "DISPATCH_QUEUE_")]
|
||||
public class DispatchQueueAttr {
|
||||
public static DispatchQueueAttr SERIAL;
|
||||
public static DispatchQueueAttr SERIAL_INACTIVE;
|
||||
public static DispatchQueueAttr CONCURRENT;
|
||||
public static DispatchQueueAttr CONCURRENT_INACTIVE;
|
||||
public static DispatchQueueAttr SERIAL_WITH_AUTORELEASE_POOL;
|
||||
public static DispatchQueueAttr CONCURRENT_WITH_AUTORELEASE_POOL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
[CCode (cheader_filename = "IOKit/IOKitLib.h", gir_namespace = "Darwin", gir_version = "1.0")]
|
||||
namespace Darwin.IOKit {
|
||||
using CoreFoundation;
|
||||
using Darwin.XNU;
|
||||
|
||||
[CCode (cname = "IOMasterPort")]
|
||||
public KernReturn main_port (MachPort bootstrap_port, out MachPort main_port);
|
||||
|
||||
[CCode (cname = "IOServiceMatching")]
|
||||
public MutableDictionary service_matching (string name);
|
||||
|
||||
[CCode (cname = "IOServiceGetMatchingServices")]
|
||||
public KernReturn get_matching_services (MachPort main_port, owned MutableDictionary matching_dict,
|
||||
out IOIterator iterator);
|
||||
|
||||
[CCode (cname = "kIOEthernetInterfaceClass", cheader_filename = "IOKit/network/IOEthernetInterface.h")]
|
||||
public const string ETHERNET_INTERFACE_CLASS;
|
||||
|
||||
[CCode (cname = "kIOBSDNameKey", cheader_filename = "IOKit/IOBSD.h")]
|
||||
public const string BSD_NAME_KEY;
|
||||
|
||||
[CCode (cname = "kIOServicePlane", cheader_filename = "IOKit/IOKitKeys.h")]
|
||||
public const string IOSERVICE_PLANE;
|
||||
|
||||
[CCode (cname = "io_registry_entry_t", destroy_function = "IOObjectRelease", has_type_id = false)]
|
||||
public struct IORegistryEntry : IOObject {
|
||||
[CCode (cname = "IORegistryEntryCreateCFProperties")]
|
||||
public KernReturn create_cf_properties (out MutableDictionary properties, Allocator? allocator, uint options);
|
||||
|
||||
[CCode (cname = "IORegistryEntryCreateCFProperty")]
|
||||
public CoreFoundation.Type create_cf_property (String key, Allocator? allocator, uint options);
|
||||
|
||||
[CCode (cname = "IORegistryEntryGetParentEntry")]
|
||||
public KernReturn get_parent_entry (string plane, out IOObject parent);
|
||||
}
|
||||
|
||||
[CCode (cname = "io_iterator_t", destroy_function = "IOObjectRelease")]
|
||||
public struct IOIterator : MachPort {
|
||||
[CCode (cname = "IOIteratorReset")]
|
||||
public void reset ();
|
||||
|
||||
[CCode (cname = "IOIteratorIsValid")]
|
||||
public bool is_valid ();
|
||||
|
||||
[CCode (cname = "IOIteratorNext")]
|
||||
public IOObject next ();
|
||||
}
|
||||
|
||||
[CCode (cname = "io_service_t", destroy_function = "IOObjectRelease", has_type_id = false)]
|
||||
public struct IOService : IOObject {
|
||||
}
|
||||
|
||||
[CCode (cname = "io_object_t", destroy_function = "IOObjectRelease", has_type_id = false)]
|
||||
public struct IOObject : MachPort {
|
||||
[CCode (cname = "IO_OBJECT_NULL")]
|
||||
public const IOObject NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
[CCode (cheader_filename = "net/if.h", lower_case_cprefix = "", gir_namespace = "Darwin", gir_version = "1.0")]
|
||||
namespace Darwin.Net {
|
||||
public const int IFNAMSIZ;
|
||||
|
||||
public unowned string? if_indextoname (uint ifindex, [CCode (array_length = false)] char[] ifname);
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
[CCode (lower_case_cprefix = "", gir_namespace = "Darwin", gir_version = "1.0")]
|
||||
namespace Darwin.XNU {
|
||||
[CCode (cname = "kern_return_t", cheader_filename = "mach/mach_error.h", cprefix = "KERN_", has_type_id = false)]
|
||||
public enum KernReturn {
|
||||
SUCCESS,
|
||||
INVALID_ADDRESS,
|
||||
PROTECTION_FAILURE,
|
||||
NO_SPACE,
|
||||
INVALID_ARGUMENT,
|
||||
FAILURE,
|
||||
RESOURCE_SHORTAGE,
|
||||
NOT_RECEIVER,
|
||||
NO_ACCESS,
|
||||
MEMORY_FAILURE,
|
||||
MEMORY_ERROR,
|
||||
ALREADY_IN_SET,
|
||||
NOT_IN_SET,
|
||||
NAME_EXISTS,
|
||||
ABORTED,
|
||||
INVALID_NAME,
|
||||
INVALID_TASK,
|
||||
INVALID_RIGHT,
|
||||
INVALID_VALUE,
|
||||
UREFS_OVERFLOW,
|
||||
INVALID_CAPABILITY,
|
||||
RIGHT_EXISTS,
|
||||
INVALID_HOST,
|
||||
MEMORY_PRESENT,
|
||||
MEMORY_DATA_MOVED,
|
||||
MEMORY_RESTART_COPY,
|
||||
INVALID_PROCESSOR_SET,
|
||||
POLICY_LIMIT,
|
||||
INVALID_POLICY,
|
||||
INVALID_OBJECT,
|
||||
ALREADY_WAITING,
|
||||
DEFAULT_SET,
|
||||
EXCEPTION_PROTECTED,
|
||||
INVALID_LEDGER,
|
||||
INVALID_MEMORY_CONTROL,
|
||||
INVALID_SECURITY,
|
||||
NOT_DEPRESSED,
|
||||
TERMINATED,
|
||||
LOCK_SET_DESTROYED,
|
||||
LOCK_UNSTABLE,
|
||||
LOCK_OWNED,
|
||||
LOCK_OWNED_SELF,
|
||||
SEMAPHORE_DESTROYED,
|
||||
RPC_SERVER_TERMINATED,
|
||||
RPC_TERMINATE_ORPHAN,
|
||||
RPC_CONTINUE_ORPHAN,
|
||||
NOT_SUPPORTED,
|
||||
NODE_DOWN,
|
||||
NOT_WAITING,
|
||||
OPERATION_TIMED_OUT,
|
||||
CODESIGN_ERROR,
|
||||
POLICY_STATIC,
|
||||
INSUFFICIENT_BUFFER_SIZE,
|
||||
DENIED,
|
||||
MISSING_KC,
|
||||
INVALID_KC,
|
||||
NOT_FOUND,
|
||||
RETURN_MAX,
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "mach/mach_error.h")]
|
||||
public static unowned string mach_error_string (KernReturn kr);
|
||||
|
||||
[CCode (cname = "mach_port_t", has_type_id = false)]
|
||||
public struct MachPort : uint {
|
||||
[CCode (cname = "MACH_PORT_NULL")]
|
||||
public const MachPort NULL;
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "libproc.h")]
|
||||
public int proc_pidpath (int pid, char[] buffer);
|
||||
|
||||
[CCode (cheader_filename = "sys/sysctl.h")]
|
||||
public int sysctlbyname (string name, void * oldp, size_t * oldlenp, void * newp = null, size_t newlen = 0);
|
||||
|
||||
[CCode (cname = "struct xinpgen", cheader_filename = "netinet/in_pcb.h")]
|
||||
public struct InetPcbGeneration {
|
||||
[CCode (cname = "xig_len")]
|
||||
public int32 length;
|
||||
[CCode (cname = "xig_count")]
|
||||
public uint count;
|
||||
[CCode (cname = "xig_gen")]
|
||||
public uint64 generation_count;
|
||||
[CCode (cname = "xig_sogen")]
|
||||
public uint64 socket_generation_count;
|
||||
}
|
||||
|
||||
[CCode (cname = "struct in_addr_4in6", cheader_filename = "netinet/in_pcb.h")]
|
||||
public struct InetAddr4in6 {
|
||||
[CCode (cname = "ia46_addr4")]
|
||||
public Posix.InAddr addr4;
|
||||
}
|
||||
|
||||
[CCode (cprefix = "INP_", cheader_filename = "netinet/in_pcb.h")]
|
||||
public enum InetVersionFlags {
|
||||
IPV4,
|
||||
IPV6,
|
||||
V4MAPPEDV6,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
[CCode (cheader_filename = "xpc/xpc.h", lower_case_cprefix = "xpc_", gir_namespace = "Darwin", gir_version = "1.0")]
|
||||
namespace Darwin.Xpc {
|
||||
[Compact]
|
||||
[CCode (cname = "gpointer", ref_function = "xpc_retain", unref_function = "xpc_release")]
|
||||
public class Connection {
|
||||
public static Connection create (string? name, GCD.DispatchQueue targetq);
|
||||
public static Connection create_mach_service (string? name, GCD.DispatchQueue targetq, uint64 flags = 0);
|
||||
|
||||
[CCode (cname = "_frida_xpc_connection_set_event_handler", cheader_filename = "frida-darwin.h")]
|
||||
public void set_event_handler (Handler handler);
|
||||
|
||||
public void activate ();
|
||||
public void cancel ();
|
||||
|
||||
public void send_message (Object message);
|
||||
[CCode (cname = "_frida_xpc_connection_send_message_with_reply", cheader_filename = "frida-darwin.h")]
|
||||
public void send_message_with_reply (Object message, GCD.DispatchQueue replyq, owned Handler handler);
|
||||
}
|
||||
|
||||
[CCode (cname = "FridaXpcHandler")]
|
||||
public delegate void Handler (Object object);
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "gpointer", ref_function = "xpc_retain", unref_function = "xpc_release")]
|
||||
public class Object {
|
||||
public Type type {
|
||||
[CCode (cname = "xpc_get_type")]
|
||||
get;
|
||||
}
|
||||
|
||||
[CCode (cname = "_frida_xpc_object_to_string", cheader_filename = "frida-darwin.h")]
|
||||
public string to_string ();
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "gpointer")]
|
||||
public class Type {
|
||||
public string name {
|
||||
get;
|
||||
}
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "gpointer")]
|
||||
public class Bool : Object {
|
||||
[CCode (cname = "XPC_TYPE_BOOL")]
|
||||
public static Type TYPE;
|
||||
|
||||
[CCode (cname = "xpc_bool_create")]
|
||||
public Bool (bool val);
|
||||
|
||||
public bool get_value ();
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "gpointer")]
|
||||
public class Int64 : Object {
|
||||
[CCode (cname = "XPC_TYPE_INT64")]
|
||||
public static Type TYPE;
|
||||
|
||||
[CCode (cname = "xpc_int64_create")]
|
||||
public Int64 (int64 val);
|
||||
|
||||
public int64 get_value ();
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "gpointer")]
|
||||
public class UInt64 : Object {
|
||||
[CCode (cname = "XPC_TYPE_UINT64")]
|
||||
public static Type TYPE;
|
||||
|
||||
[CCode (cname = "xpc_uint64_create")]
|
||||
public UInt64 (uint64 val);
|
||||
|
||||
public uint64 get_value ();
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "gpointer")]
|
||||
public class String : Object {
|
||||
[CCode (cname = "XPC_TYPE_STRING")]
|
||||
public static Type TYPE;
|
||||
|
||||
[CCode (cname = "xpc_string_create")]
|
||||
public String (string val);
|
||||
|
||||
public unowned string get_string_ptr ();
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "gpointer")]
|
||||
public class Uuid : Object {
|
||||
[CCode (cname = "XPC_TYPE_UUID")]
|
||||
public static Type TYPE;
|
||||
|
||||
[CCode (array_length = false)]
|
||||
public unowned uint8[] get_bytes ();
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "gpointer")]
|
||||
public class Array : Object {
|
||||
[CCode (cname = "XPC_TYPE_ARRAY")]
|
||||
public static Type TYPE;
|
||||
|
||||
public size_t count {
|
||||
get;
|
||||
}
|
||||
|
||||
[CCode (cname = "xpc_array_create_empty")]
|
||||
public Array ();
|
||||
|
||||
public unowned Object? get_value (size_t index);
|
||||
public void set_value (size_t index, Object val);
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "gpointer")]
|
||||
public class Dictionary : Object {
|
||||
[CCode (cname = "XPC_TYPE_DICTIONARY")]
|
||||
public static Type TYPE;
|
||||
|
||||
[CCode (cname = "xpc_dictionary_create_empty")]
|
||||
public Dictionary ();
|
||||
|
||||
public bool get_bool (string key);
|
||||
public void set_bool (string key, bool val);
|
||||
|
||||
public int64 get_int64 (string key);
|
||||
public void set_int64 (string key, int64 val);
|
||||
|
||||
public uint64 get_uint64 (string key);
|
||||
public void set_uint64 (string key, uint64 val);
|
||||
|
||||
public unowned string? get_string (string key);
|
||||
public void set_string (string key, string val);
|
||||
|
||||
public unowned Dictionary? get_dictionary (string key);
|
||||
|
||||
public unowned Object? get_value (string key);
|
||||
public void set_value (string key, Object val);
|
||||
|
||||
[CCode (cname = "_frida_xpc_dictionary_apply", cheader_filename = "frida-darwin.h")]
|
||||
public bool apply (DictionaryApplier applier);
|
||||
|
||||
public Connection? create_connection (string key);
|
||||
}
|
||||
|
||||
[CCode (cname = "FridaXpcDictionaryApplier")]
|
||||
public delegate bool DictionaryApplier (string key, Object val);
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "gpointer")]
|
||||
public class Error : Dictionary {
|
||||
[CCode (cname = "XPC_TYPE_ERROR")]
|
||||
public static Type TYPE;
|
||||
|
||||
public const string KEY_DESCRIPTION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,358 @@
|
||||
[CCode (cheader_filename = "nghttp2/nghttp2.h", cprefix = "nghttp2_", gir_namespace = "NGHttp2", gir_version = "1.0")]
|
||||
namespace NGHttp2 {
|
||||
[Compact]
|
||||
[CCode (cname = "nghttp2_session", cprefix = "nghttp2_session_", free_function = "nghttp2_session_del")]
|
||||
public class Session {
|
||||
[CCode (cname = "nghttp2_session_client_new2")]
|
||||
public static int make_client (out Session session, SessionCallbacks callbacks, void * user_data, Option? option = null);
|
||||
|
||||
[CCode (cname = "nghttp2_submit_settings")]
|
||||
public int submit_settings (uint8 flags, SettingsEntry[] entries);
|
||||
|
||||
[CCode (cname = "nghttp2_submit_window_update")]
|
||||
public int submit_window_update (uint8 flags, int32 stream_id, int32 window_size_increment);
|
||||
|
||||
public int set_local_window_size (uint8 flags, int32 stream_id, int32 window_size);
|
||||
|
||||
[CCode (cname = "nghttp2_submit_request")]
|
||||
public int32 submit_request (PrioritySpec? pri_spec, NV[] nvs, DataProvider? data_prd, void * stream_user_data);
|
||||
|
||||
[CCode (cname = "nghttp2_submit_headers")]
|
||||
public int32 submit_headers (uint8 flags, int32 stream_id, PrioritySpec? pri_spec, NV[] nvs, void * stream_user_data);
|
||||
|
||||
[CCode (cname = "nghttp2_submit_data")]
|
||||
public int submit_data (uint8 flags, int32 stream_id, DataProvider data_prd);
|
||||
|
||||
public int send ();
|
||||
|
||||
public ssize_t mem_recv (uint8[] input);
|
||||
|
||||
public bool want_read ();
|
||||
|
||||
public bool want_write ();
|
||||
|
||||
public int consume_connection (size_t size);
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "nghttp2_session_callbacks", cprefix = "nghttp2_session_callbacks_",
|
||||
free_function = "nghttp2_session_callbacks_del")]
|
||||
public class SessionCallbacks {
|
||||
[CCode (cname = "nghttp2_session_callbacks_new")]
|
||||
public static int make (out SessionCallbacks callbacks);
|
||||
|
||||
public void set_send_callback (SendCallback callback);
|
||||
public void set_on_frame_recv_callback (OnFrameRecvCallback callback);
|
||||
public void set_on_data_chunk_recv_callback (OnDataChunkRecvCallback callback);
|
||||
public void set_before_frame_send_callback (BeforeFrameSendCallback callback);
|
||||
public void set_on_frame_send_callback (OnFrameSendCallback callback);
|
||||
public void set_on_frame_not_send_callback (OnFrameNotSendCallback callback);
|
||||
public void set_on_stream_close_callback (OnStreamCloseCallback callback);
|
||||
public void set_on_begin_frame_callback (OnBeginFrameCallback callback);
|
||||
[CCode (cname = "nghttp2_session_callbacks_set_error_callback2")]
|
||||
public void set_error_callback (ErrorCallback callback);
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_send_callback", has_target = false)]
|
||||
public delegate ssize_t SendCallback (Session session, [CCode (array_length_type = "size_t")] uint8[] data, int flags,
|
||||
void * user_data);
|
||||
|
||||
[CCode (cname = "nghttp2_on_frame_recv_callback", has_target = false)]
|
||||
public delegate int OnFrameRecvCallback (Session session, Frame frame, void * user_data);
|
||||
|
||||
[CCode (cname = "nghttp2_on_data_chunk_recv_callback", has_target = false)]
|
||||
public delegate int OnDataChunkRecvCallback (Session session, uint8 flags, int32 stream_id,
|
||||
[CCode (array_length_type = "size_t")] uint8[] data, void * user_data);
|
||||
|
||||
[CCode (cname = "nghttp2_before_frame_send_callback", has_target = false)]
|
||||
public delegate int BeforeFrameSendCallback (Session session, Frame frame, void * user_data);
|
||||
|
||||
[CCode (cname = "nghttp2_on_frame_send_callback", has_target = false)]
|
||||
public delegate int OnFrameSendCallback (Session session, Frame frame, void * user_data);
|
||||
|
||||
[CCode (cname = "nghttp2_on_frame_not_send_callback", has_target = false)]
|
||||
public delegate int OnFrameNotSendCallback (Session session, Frame frame, ErrorCode lib_error_code, void * user_data);
|
||||
|
||||
[CCode (cname = "nghttp2_on_stream_close_callback", has_target = false)]
|
||||
public delegate int OnStreamCloseCallback (Session session, int32 stream_id, uint32 error_code, void * user_data);
|
||||
|
||||
[CCode (cname = "nghttp2_on_begin_frame_callback", has_target = false)]
|
||||
public delegate int OnBeginFrameCallback (Session session, FrameHd hd, void * user_data);
|
||||
|
||||
[CCode (cname = "nghttp2_error_callback2", has_target = false)]
|
||||
public delegate int ErrorCallback (Session session, ErrorCode code, [CCode (array_length_type = "size_t")] char[] msg,
|
||||
void * user_data);
|
||||
|
||||
[CCode (cname = "nghttp2_frame")]
|
||||
public struct Frame {
|
||||
public FrameHd hd;
|
||||
public DataFrame data;
|
||||
public HeadersFrame headers;
|
||||
public PriorityFrame priority;
|
||||
public RstStreamFrame rst_stream;
|
||||
public SettingsFrame settings;
|
||||
public PushPromiseFrame push_promise;
|
||||
public PingFrame ping;
|
||||
public GoawayFrame goaway;
|
||||
public WindowUpdateFrame window_update;
|
||||
public ExtensionFrame ext;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_frame_type", cprefix = "NGHTTP2_", has_type_id = false)]
|
||||
public enum FrameType {
|
||||
DATA,
|
||||
HEADERS,
|
||||
PRIORITY,
|
||||
RST_STREAM,
|
||||
SETTINGS,
|
||||
PUSH_PROMISE,
|
||||
PING,
|
||||
GOAWAY,
|
||||
WINDOW_UPDATE,
|
||||
CONTINUATION,
|
||||
ALTSVC,
|
||||
ORIGIN,
|
||||
PRIORITY_UPDATE,
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_frame_hd")]
|
||||
public struct FrameHd {
|
||||
public size_t length;
|
||||
public int32 stream_id;
|
||||
public FrameType type;
|
||||
public uint8 flags;
|
||||
public uint8 reserved;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_data")]
|
||||
public struct DataFrame {
|
||||
public FrameHd hd;
|
||||
public size_t padlen;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_headers")]
|
||||
public struct HeadersFrame {
|
||||
public FrameHd hd;
|
||||
public size_t padlen;
|
||||
public PrioritySpec pri_spec;
|
||||
public NV * nva;
|
||||
public size_t nvlen;
|
||||
public HeadersCategory cat;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_headers_category", cprefix = "NGHTTP2_HCAT_", has_type_id = false)]
|
||||
public enum HeadersCategory {
|
||||
REQUEST,
|
||||
RESPONSE,
|
||||
PUSH_RESPONSE,
|
||||
HEADERS,
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_priority")]
|
||||
public struct PriorityFrame {
|
||||
public FrameHd hd;
|
||||
public PrioritySpec pri_spec;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_rst_stream")]
|
||||
public struct RstStreamFrame {
|
||||
public FrameHd hd;
|
||||
public uint32 error_code;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_settings")]
|
||||
public struct SettingsFrame {
|
||||
public FrameHd hd;
|
||||
public size_t niv;
|
||||
public SettingsEntry * iv;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_push_promise")]
|
||||
public struct PushPromiseFrame {
|
||||
public FrameHd hd;
|
||||
public size_t padlen;
|
||||
public NV * nva;
|
||||
public size_t nvlen;
|
||||
public int32 promised_stream_id;
|
||||
public uint8 reserved;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_ping")]
|
||||
public struct PingFrame {
|
||||
public FrameHd hd;
|
||||
public uint8[] opaque_data;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_goaway")]
|
||||
public struct GoawayFrame {
|
||||
public FrameHd hd;
|
||||
public int32 last_stream_id;
|
||||
public uint32 error_code;
|
||||
public uint8 * opaque_data;
|
||||
public size_t opaque_data_len;
|
||||
public uint8 reserved;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_window_update")]
|
||||
public struct WindowUpdateFrame {
|
||||
public FrameHd hd;
|
||||
public int32 window_size_increment;
|
||||
public uint8 reserved;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_extension")]
|
||||
public struct ExtensionFrame {
|
||||
public FrameHd hd;
|
||||
public void * payload;
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "nghttp2_option", cprefix = "nghttp2_option_", free_function = "nghttp2_option_del")]
|
||||
public class Option {
|
||||
[CCode (cname = "nghttp2_option_new")]
|
||||
public static int make (out Option option);
|
||||
|
||||
public void set_no_auto_window_update (bool val);
|
||||
public void set_peer_max_concurrent_streams (uint32 val);
|
||||
public void set_no_recv_client_magic (bool val);
|
||||
public void set_no_http_messaging (bool val);
|
||||
public void set_no_http_semantics (bool val);
|
||||
public void set_max_reserved_remote_streams (uint32 val);
|
||||
public void set_user_recv_extension_type (uint8 type);
|
||||
public void set_builtin_recv_extension_type (uint8 type);
|
||||
public void set_no_auto_ping_ack (bool val);
|
||||
public void set_max_send_header_block_length (size_t val);
|
||||
public void set_max_deflate_dynamic_table_size (size_t val);
|
||||
public void set_no_closed_streams (bool val);
|
||||
public void set_max_outbound_ack (size_t val);
|
||||
public void set_max_settings (size_t val);
|
||||
public void set_server_fallback_rfc7540_priorities (bool val);
|
||||
public void set_no_rfc9113_leading_and_trailing_ws_validation (bool val);
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_settings_entry")]
|
||||
public struct SettingsEntry {
|
||||
public SettingsId settings_id;
|
||||
public uint32 value;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_settings_id", cprefix = "NGHTTP2_SETTINGS_", has_type_id = false)]
|
||||
public enum SettingsId {
|
||||
HEADER_TABLE_SIZE,
|
||||
ENABLE_PUSH,
|
||||
MAX_CONCURRENT_STREAMS,
|
||||
INITIAL_WINDOW_SIZE,
|
||||
MAX_FRAME_SIZE,
|
||||
MAX_HEADER_LIST_SIZE,
|
||||
ENABLE_CONNECT_PROTOCOL,
|
||||
NO_RFC7540_PRIORITIES,
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_priority_spec")]
|
||||
public struct PrioritySpec {
|
||||
public int32 stream_id;
|
||||
public int32 weight;
|
||||
public uint8 exclusive;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_nv")]
|
||||
public struct NV {
|
||||
public uint8 * name;
|
||||
public uint8 * value;
|
||||
public size_t namelen;
|
||||
public size_t valuelen;
|
||||
public NVFlag flags;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_nv_flag", cprefix = "NGHTTP2_NV_FLAG_", has_type_id = false)]
|
||||
[Flags]
|
||||
public enum NVFlag {
|
||||
NONE,
|
||||
NO_INDEX,
|
||||
NO_COPY_NAME,
|
||||
NO_COPY_VALUE,
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_data_provider")]
|
||||
public struct DataProvider {
|
||||
public DataSource source;
|
||||
public DataSourceReadCallback read_callback;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_data_source")]
|
||||
public struct DataSource {
|
||||
public void * ptr;
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_data_source_read_callback", has_target = false)]
|
||||
public delegate ssize_t DataSourceReadCallback (Session session, int32 stream_id,
|
||||
[CCode (array_length_type = "size_t")] uint8[] buf, ref uint32 data_flags, DataSource source, void * user_data);
|
||||
|
||||
[CCode (cname = "nghttp2_strerror")]
|
||||
public unowned string strerror (ssize_t result);
|
||||
|
||||
[CCode (cname = "nghttp2_error", cprefix = "NGHTTP2_ERR_", has_type_id = false)]
|
||||
public enum ErrorCode {
|
||||
INVALID_ARGUMENT,
|
||||
BUFFER_ERROR,
|
||||
UNSUPPORTED_VERSION,
|
||||
WOULDBLOCK,
|
||||
PROTO,
|
||||
INVALID_FRAME,
|
||||
EOF,
|
||||
DEFERRED,
|
||||
STREAM_ID_NOT_AVAILABLE,
|
||||
STREAM_CLOSED,
|
||||
STREAM_CLOSING,
|
||||
STREAM_SHUT_WR,
|
||||
INVALID_STREAM_ID,
|
||||
INVALID_STREAM_STATE,
|
||||
DEFERRED_DATA_EXIST,
|
||||
START_STREAM_NOT_ALLOWED,
|
||||
GOAWAY_ALREADY_SENT,
|
||||
INVALID_HEADER_BLOCK,
|
||||
INVALID_STATE,
|
||||
TEMPORAL_CALLBACK_FAILURE,
|
||||
FRAME_SIZE_ERROR,
|
||||
HEADER_COMP,
|
||||
FLOW_CONTROL,
|
||||
INSUFF_BUFSIZE,
|
||||
PAUSE,
|
||||
TOO_MANY_INFLIGHT_SETTINGS,
|
||||
PUSH_DISABLED,
|
||||
DATA_EXIST,
|
||||
SESSION_CLOSING,
|
||||
HTTP_HEADER,
|
||||
HTTP_MESSAGING,
|
||||
REFUSED_STREAM,
|
||||
INTERNAL,
|
||||
CANCEL,
|
||||
SETTINGS_EXPECTED,
|
||||
TOO_MANY_SETTINGS,
|
||||
FATAL,
|
||||
NOMEM,
|
||||
CALLBACK_FAILURE,
|
||||
BAD_CLIENT_MAGIC,
|
||||
FLOODED,
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_flag", cprefix = "NGHTTP2_FLAG_", has_type_id = false)]
|
||||
[Flags]
|
||||
public enum Flag {
|
||||
NONE,
|
||||
END_STREAM,
|
||||
END_HEADERS,
|
||||
ACK,
|
||||
PADDED,
|
||||
PRIORITY,
|
||||
}
|
||||
|
||||
[CCode (cname = "nghttp2_data_flag", cprefix = "NGHTTP2_DATA_FLAG_", has_type_id = false)]
|
||||
[Flags]
|
||||
public enum DataFlag {
|
||||
NONE,
|
||||
EOF,
|
||||
NO_END_STREAM,
|
||||
NO_COPY,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,535 @@
|
||||
[CCode (cheader_filename = "ngtcp2/ngtcp2.h", lower_case_cprefix = "ngtcp2_", gir_namespace = "NGTcp2", gir_version = "1.0")]
|
||||
namespace NGTcp2 {
|
||||
[Compact]
|
||||
[CCode (cname = "ngtcp2_conn", cprefix = "ngtcp2_conn_", free_function = "ngtcp2_conn_del")]
|
||||
public class Connection {
|
||||
[CCode (cname = "ngtcp2_conn_client_new")]
|
||||
public static int make_client (out Connection conn, ConnectionID dcid, ConnectionID scid, Path path,
|
||||
ProtocolVersion client_chosen_version, Callbacks callbacks, Settings settings, TransportParams params,
|
||||
MemoryAllocator? mem, void * user_data);
|
||||
|
||||
public void set_tls_native_handle (void * tls_native_handle);
|
||||
|
||||
public void set_keep_alive_timeout (Duration timeout);
|
||||
|
||||
public Timestamp get_expiry ();
|
||||
public int handle_expiry (Timestamp ts);
|
||||
|
||||
[CCode (cname = "ngtcp2_conn_read_pkt")]
|
||||
public int read_packet (Path path, PacketInfo * pi, uint8[] pkt, Timestamp ts);
|
||||
|
||||
public int open_bidi_stream (out int64 stream_id, void * stream_user_data);
|
||||
|
||||
public ssize_t write_stream (Path * path, PacketInfo * pi, uint8[] dest, ssize_t * pdatalen, WriteStreamFlags flags,
|
||||
int64 stream_id, uint8[]? data, Timestamp ts);
|
||||
public ssize_t writev_stream (Path * path, PacketInfo * pi, uint8[] dest, ssize_t * pdatalen, WriteStreamFlags flags,
|
||||
int64 stream_id, IOVector[] datav, Timestamp ts);
|
||||
|
||||
public ssize_t write_datagram (Path * path, PacketInfo * pi, uint8[] dest, int * paccepted, uint32 flags, uint64 dgram_id,
|
||||
uint8[] data, Timestamp ts);
|
||||
public ssize_t writev_datagram (Path * path, PacketInfo * pi, uint8[] dest, int * paccepted, uint32 flags, uint64 dgram_id,
|
||||
IOVector[] datav, Timestamp ts);
|
||||
|
||||
public uint64 get_max_data_left ();
|
||||
public uint64 get_max_stream_data_left (int64 stream_id);
|
||||
}
|
||||
|
||||
public unowned string strerror (int liberr);
|
||||
|
||||
[CCode (cname = "int", cprefix = "NGTCP2_ERR_", has_type_id = false)]
|
||||
public enum ErrorCode {
|
||||
INVALID_ARGUMENT,
|
||||
NOBUF,
|
||||
PROTO,
|
||||
INVALID_STATE,
|
||||
ACK_FRAME,
|
||||
STREAM_ID_BLOCKED,
|
||||
STREAM_IN_USE,
|
||||
STREAM_DATA_BLOCKED,
|
||||
FLOW_CONTROL,
|
||||
CONNECTION_ID_LIMIT,
|
||||
STREAM_LIMIT,
|
||||
FINAL_SIZE,
|
||||
CRYPTO,
|
||||
PKT_NUM_EXHAUSTED,
|
||||
REQUIRED_TRANSPORT_PARAM,
|
||||
MALFORMED_TRANSPORT_PARAM,
|
||||
FRAME_ENCODING,
|
||||
DECRYPT,
|
||||
STREAM_SHUT_WR,
|
||||
STREAM_NOT_FOUND,
|
||||
STREAM_STATE,
|
||||
RECV_VERSION_NEGOTIATION,
|
||||
CLOSING,
|
||||
DRAINING,
|
||||
TRANSPORT_PARAM,
|
||||
DISCARD_PKT,
|
||||
CONN_ID_BLOCKED,
|
||||
INTERNAL,
|
||||
CRYPTO_BUFFER_EXCEEDED,
|
||||
WRITE_MORE,
|
||||
RETRY,
|
||||
DROP_CONN,
|
||||
AEAD_LIMIT_REACHED,
|
||||
NO_VIABLE_PATH,
|
||||
VERSION_NEGOTIATION,
|
||||
HANDSHAKE_TIMEOUT,
|
||||
VERSION_NEGOTIATION_FAILURE,
|
||||
IDLE_CLOSE,
|
||||
FATAL,
|
||||
NOMEM,
|
||||
CALLBACK_FAILURE,
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_cid", has_destroy_function = false)]
|
||||
public struct ConnectionID {
|
||||
public size_t datalen;
|
||||
public uint8 data[MAX_CIDLEN];
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_connection_id_status_type", cprefix = "NGTCP2_CONNECTION_ID_STATUS_TYPE_", has_type_id = false)]
|
||||
public enum ConnectionIdStatusType {
|
||||
ACTIVATE,
|
||||
DEACTIVATE,
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_path", has_destroy_function = false)]
|
||||
public struct Path {
|
||||
public Address local;
|
||||
public Address remote;
|
||||
public void * user_data;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_path_validation_result", cprefix = "NGTCP2_PATH_VALIDATION_RESULT_", has_type_id = false)]
|
||||
public enum PathValidationResult {
|
||||
SUCCESS,
|
||||
FAILURE,
|
||||
ABORTED,
|
||||
}
|
||||
|
||||
[CCode (cname = "uint32_t", cprefix = "NGTCP2_PROTO_VER_", has_type_id = false)]
|
||||
public enum ProtocolVersion {
|
||||
V1,
|
||||
V2,
|
||||
MIN,
|
||||
MAX,
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_pkt_info", has_destroy_function = false)]
|
||||
public struct PacketInfo {
|
||||
public uint8 ecn;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_pkt_hd", has_destroy_function = false)]
|
||||
public struct PacketHeader {
|
||||
public ConnectionID dcid;
|
||||
public ConnectionID scid;
|
||||
public int64 pkt_num;
|
||||
[CCode (array_length_cname = "tokenlen")]
|
||||
public uint8[]? token;
|
||||
public size_t pkt_numlen;
|
||||
public size_t len;
|
||||
public uint32 version;
|
||||
public uint8 type;
|
||||
public uint8 flags;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_pkt_stateless_reset", has_destroy_function = false)]
|
||||
public struct PacketStatelessReset {
|
||||
public uint8 stateless_reset_token[STATELESS_RESET_TOKENLEN];
|
||||
[CCode (array_length_cname = "randlen")]
|
||||
public uint8[] rand;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
[CCode (cname = "uint32_t", cprefix = "NGTCP2_WRITE_STREAM_FLAG_", has_type_id = false)]
|
||||
public enum WriteStreamFlags {
|
||||
NONE,
|
||||
MORE,
|
||||
FIN,
|
||||
}
|
||||
|
||||
[CCode (cname = "NGTCP2_MAX_CIDLEN")]
|
||||
public const size_t MAX_CIDLEN;
|
||||
[CCode (cname = "NGTCP2_MIN_INITIAL_DCIDLEN")]
|
||||
public const size_t MIN_INITIAL_DCIDLEN;
|
||||
|
||||
[CCode (cname = "NGTCP2_STATELESS_RESET_TOKENLEN")]
|
||||
public const size_t STATELESS_RESET_TOKENLEN;
|
||||
|
||||
[CCode (cname = "ngtcp2_vec", has_destroy_function = false)]
|
||||
public struct IOVector {
|
||||
[CCode (array_length_cname = "len")]
|
||||
public unowned uint8[] base;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_sa_family", cprefix = "NGTCP2_AF_", has_type_id = false)]
|
||||
public enum SocketAddressFamily {
|
||||
INET,
|
||||
INET6,
|
||||
}
|
||||
|
||||
[SimpleType]
|
||||
[CCode (cname = "ngtcp2_in_port")]
|
||||
public struct InternetPort : uint16 {
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_sockaddr", has_destroy_function = false)]
|
||||
public struct SocketAddress {
|
||||
public SocketAddressFamily sa_family;
|
||||
public uint8 sa_data[14];
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_in_addr", has_destroy_function = false)]
|
||||
public struct InternetAddress {
|
||||
public uint32 s_addr;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_sockaddr_in", has_destroy_function = false)]
|
||||
public struct SocketAddressInternet {
|
||||
public SocketAddressFamily sin_family;
|
||||
public InternetPort sin_port;
|
||||
public InternetAddress sin_addr;
|
||||
public uint8 sin_zero[8];
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_in6_addr", has_destroy_function = false)]
|
||||
public struct Internet6Address {
|
||||
public uint8 in6_addr[16];
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_sockaddr_in6", has_destroy_function = false)]
|
||||
public struct SocketAddressInternet6 {
|
||||
public SocketAddressFamily sin6_family;
|
||||
public InternetPort sin6_port;
|
||||
public uint32 sin6_flowinfo;
|
||||
public Internet6Address sin6_addr;
|
||||
public uint32 sin6_scope_id;
|
||||
}
|
||||
|
||||
[SimpleType]
|
||||
[CCode (cname = "ngtcp2_socklen")]
|
||||
public struct SocketLength : uint32 {
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_addr", has_destroy_function = false)]
|
||||
public struct Address {
|
||||
[CCode (array_length_cname = "addrlen")]
|
||||
public uint8[] addr;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_preferred_addr", has_destroy_function = false)]
|
||||
public struct PreferredAddress {
|
||||
public ConnectionID cid;
|
||||
public SocketAddressInternet ipv4;
|
||||
public SocketAddressInternet6 ipv6;
|
||||
public uint8 ipv4_present;
|
||||
public uint8 ipv6_present;
|
||||
public uint8 stateless_reset_token[STATELESS_RESET_TOKENLEN];
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_version_info", has_destroy_function = false)]
|
||||
public struct VersionInfo {
|
||||
public uint32 chosen_version;
|
||||
[CCode (array_length_cname = "available_versionslen")]
|
||||
public uint8[] available_versions;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_encryption_level", cprefix = "NGTCP2_ENCRYPTION_LEVEL_", has_type_id = false)]
|
||||
public enum EncryptionLevel {
|
||||
INITIAL,
|
||||
HANDSHAKE,
|
||||
1RTT,
|
||||
0RTT,
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_token_type", cprefix = "NGTCP2_TOKEN_TYPE_", has_type_id = false)]
|
||||
public enum TokenType {
|
||||
UNKNOWN,
|
||||
RETRY,
|
||||
NEW_TOKEN,
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_rand_ctx", has_destroy_function = false)]
|
||||
public struct RNGContext {
|
||||
public void * native_handle;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_crypto_aead", has_destroy_function = false)]
|
||||
public struct CryptoAead {
|
||||
public void * native_handle;
|
||||
public size_t max_overhead;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_crypto_cipher", has_destroy_function = false)]
|
||||
public struct CryptoCipher {
|
||||
public void * native_handle;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_crypto_aead_ctx", has_destroy_function = false)]
|
||||
public struct CryptoAeadCtx {
|
||||
public void * native_handle;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_crypto_cipher_ctx", has_destroy_function = false)]
|
||||
public struct CryptoCipherCtx {
|
||||
public void * native_handle;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_cc_algo", cprefix = "NGTCP2_CC_ALGO_", has_type_id = false)]
|
||||
public enum CongestionControlAlgorithm {
|
||||
RENO,
|
||||
CUBIC,
|
||||
BBR,
|
||||
}
|
||||
|
||||
[SimpleType]
|
||||
[CCode (cname = "ngtcp2_tstamp")]
|
||||
public struct Timestamp : uint64 {
|
||||
}
|
||||
|
||||
[CCode (cname = "NGTCP2_SECONDS")]
|
||||
public const uint64 SECONDS;
|
||||
|
||||
[CCode (cname = "NGTCP2_MILLISECONDS")]
|
||||
public const uint64 MILLISECONDS;
|
||||
|
||||
[CCode (cname = "NGTCP2_MICROSECONDS")]
|
||||
public const uint64 MICROSECONDS;
|
||||
|
||||
[CCode (cname = "NGTCP2_NANOSECONDS")]
|
||||
public const uint64 NANOSECONDS;
|
||||
|
||||
[SimpleType]
|
||||
[CCode (cname = "ngtcp2_duration")]
|
||||
public struct Duration : uint64 {
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_callbacks", has_destroy_function = false)]
|
||||
public struct Callbacks {
|
||||
public ClientInitial? client_initial;
|
||||
public RecvClientInitial? recv_client_initial;
|
||||
public RecvCryptoData recv_crypto_data;
|
||||
public HandshakeCompleted? handshake_completed;
|
||||
public RecvVersionNegotiation? recv_version_negotiation;
|
||||
public Encrypt encrypt;
|
||||
public Decrypt decrypt;
|
||||
public HpMask hp_mask;
|
||||
public RecvStreamData? recv_stream_data;
|
||||
public AckedStreamDataOffset? acked_stream_data_offset;
|
||||
public StreamOpen? stream_open;
|
||||
public StreamClose? stream_close;
|
||||
public RecvStatelessReset? recv_stateless_reset;
|
||||
public RecvRetry? recv_retry;
|
||||
public ExtendMaxStreams? extend_max_local_streams_bidi;
|
||||
public ExtendMaxStreams? extend_max_local_streams_uni;
|
||||
public Rand? rand;
|
||||
public GetNewConnectionId get_new_connection_id;
|
||||
public RemoveConnectionId? remove_connection_id;
|
||||
public UpdateKey update_key;
|
||||
public PathValidation? path_validation;
|
||||
public SelectPreferredAddr? select_preferred_addr;
|
||||
public StreamReset? stream_reset;
|
||||
public ExtendMaxStreams? extend_max_remote_streams_bidi;
|
||||
public ExtendMaxStreams? extend_max_remote_streams_uni;
|
||||
public ExtendMaxStreamData? extend_max_stream_data;
|
||||
public ConnectionIdStatus? dcid_status;
|
||||
public HandshakeConfirmed? handshake_confirmed;
|
||||
public RecvNewToken? recv_new_token;
|
||||
public DeleteCryptoAeadCtx delete_crypto_aead_ctx;
|
||||
public DeleteCryptoCipherCtx delete_crypto_cipher_ctx;
|
||||
public RecvDatagram? recv_datagram;
|
||||
public AckDatagram? ack_datagram;
|
||||
public LostDatagram? lost_datagram;
|
||||
public GetPathChallengeData get_path_challenge_data;
|
||||
public StreamStopSending? stream_stop_sending;
|
||||
public VersionNegotiation version_negotiation;
|
||||
public RecvKey recv_rx_key;
|
||||
public RecvKey recv_tx_key;
|
||||
public TlsEarlyDataRejected? tls_early_data_rejected;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_client_initial", has_target = false)]
|
||||
public delegate int ClientInitial (Connection conn, void * user_data);
|
||||
[CCode (cname = "ngtcp2_recv_client_initial", has_target = false)]
|
||||
public delegate int RecvClientInitial (Connection conn, ConnectionID dcid, void * user_data);
|
||||
[CCode (cname = "ngtcp2_recv_crypto_data", has_target = false)]
|
||||
public delegate int RecvCryptoData (Connection conn, EncryptionLevel encryption_level, uint64 offset,
|
||||
[CCode (array_length_type = "size_t")] uint8[] data, void * user_data);
|
||||
[CCode (cname = "ngtcp2_handshake_completed", has_target = false)]
|
||||
public delegate int HandshakeCompleted (Connection conn, void * user_data);
|
||||
[CCode (cname = "ngtcp2_recv_version_negotiation", has_target = false)]
|
||||
public delegate int RecvVersionNegotiation (Connection conn, PacketHeader hd, [CCode (array_length_type = "size_t")] uint32[] sv,
|
||||
void * user_data);
|
||||
[CCode (cname = "ngtcp2_encrypt", has_target = false)]
|
||||
public delegate int Encrypt ([CCode (array_length = false)] uint8[] dest, CryptoAead aead, CryptoAeadCtx aead_ctx,
|
||||
[CCode (array_length_type = "size_t")] uint8[] plaintext,
|
||||
[CCode (array_length_type = "size_t")] uint8[] nonce,
|
||||
[CCode (array_length_type = "size_t")] uint8[] aad);
|
||||
[CCode (cname = "ngtcp2_decrypt", has_target = false)]
|
||||
public delegate int Decrypt ([CCode (array_length = false)] uint8[] dest, CryptoAead aead, CryptoAeadCtx aead_ctx,
|
||||
[CCode (array_length_type = "size_t")] uint8[] ciphertext,
|
||||
[CCode (array_length_type = "size_t")] uint8[] nonce,
|
||||
[CCode (array_length_type = "size_t")] uint8[] aad);
|
||||
[CCode (cname = "ngtcp2_hp_mask", has_target = false)]
|
||||
public delegate int HpMask ([CCode (array_length = false)] uint8[] dest, CryptoCipher hp, CryptoCipherCtx hp_ctx,
|
||||
[CCode (array_length = false)] uint8[] sample);
|
||||
[CCode (cname = "ngtcp2_recv_stream_data", has_target = false)]
|
||||
public delegate int RecvStreamData (Connection conn, uint32 flags, int64 stream_id, uint64 offset,
|
||||
[CCode (array_length_type = "size_t")] uint8[] data, void * user_data, void * stream_user_data);
|
||||
[CCode (cname = "ngtcp2_acked_stream_data_offset", has_target = false)]
|
||||
public delegate int AckedStreamDataOffset (Connection conn, int64 stream_id, uint64 offset, uint64 datalen, void * user_data,
|
||||
void * stream_user_data);
|
||||
[CCode (cname = "ngtcp2_stream_open", has_target = false)]
|
||||
public delegate int StreamOpen (Connection conn, int64 stream_id, void * user_data);
|
||||
[CCode (cname = "ngtcp2_stream_close", has_target = false)]
|
||||
public delegate int StreamClose (Connection conn, uint32 flags, int64 stream_id, uint64 app_error_code, void * user_data,
|
||||
void * stream_user_data);
|
||||
[CCode (cname = "ngtcp2_recv_stateless_reset", has_target = false)]
|
||||
public delegate int RecvStatelessReset (Connection conn, PacketStatelessReset sr, void * user_data);
|
||||
[CCode (cname = "ngtcp2_recv_retry", has_target = false)]
|
||||
public delegate int RecvRetry (Connection conn, PacketHeader hd, void * user_data);
|
||||
[CCode (cname = "ngtcp2_extend_max_streams", has_target = false)]
|
||||
public delegate int ExtendMaxStreams (Connection conn, uint64 max_streams, void * user_data);
|
||||
[CCode (cname = "ngtcp2_extend_max_stream_data", has_target = false)]
|
||||
public delegate int ExtendMaxStreamData (Connection conn, int64 stream_id, uint64 max_data, void * user_data,
|
||||
void * stream_user_data);
|
||||
[CCode (cname = "ngtcp2_rand", has_target = false)]
|
||||
public delegate void Rand ([CCode (array_length_type = "size_t")] uint8[] dest, RNGContext rand_ctx);
|
||||
[CCode (cname = "ngtcp2_get_new_connection_id", has_target = false)]
|
||||
public delegate int GetNewConnectionId (Connection conn, out ConnectionID cid, [CCode (array_length = false)] uint8[] token,
|
||||
size_t cidlen, void * user_data);
|
||||
[CCode (cname = "ngtcp2_remove_connection_id", has_target = false)]
|
||||
public delegate int RemoveConnectionId (Connection conn, ConnectionID cid, void * user_data);
|
||||
[CCode (cname = "ngtcp2_update_key", has_target = false)]
|
||||
public delegate int UpdateKey (Connection conn,
|
||||
[CCode (array_length = false)] uint8[] rx_secret,
|
||||
[CCode (array_length = false)] uint8[] tx_secret,
|
||||
CryptoAeadCtx rx_aead_ctx, [CCode (array_length = false)] uint8[] rx_iv,
|
||||
CryptoAeadCtx tx_aead_ctx, [CCode (array_length = false)] uint8[] tx_iv,
|
||||
[CCode (array_length_pos = 9.1)] uint8[] current_rx_secret,
|
||||
[CCode (array_length_pos = 9.1)] uint8[] current_tx_secret,
|
||||
void * user_data);
|
||||
[CCode (cname = "ngtcp2_path_validation", has_target = false)]
|
||||
public delegate int PathValidation (Connection conn, uint32 flags, Path path, Path old_path, PathValidationResult res,
|
||||
void * user_data);
|
||||
[CCode (cname = "ngtcp2_select_preferred_addr", has_target = false)]
|
||||
public delegate int SelectPreferredAddr (Connection conn, Path dest, PreferredAddress paddr, void * user_data);
|
||||
[CCode (cname = "ngtcp2_stream_reset", has_target = false)]
|
||||
public delegate int StreamReset (Connection conn, int64 stream_id, uint64 final_size, uint64 app_error_code, void * user_data,
|
||||
void * stream_user_data);
|
||||
[CCode (cname = "ngtcp2_connection_id_status", has_target = false)]
|
||||
public delegate int ConnectionIdStatus (Connection conn, ConnectionIdStatusType type, uint64 seq, ConnectionID cid,
|
||||
[CCode (array_length = false)] uint8[] token, void * user_data);
|
||||
[CCode (cname = "ngtcp2_handshake_confirmed", has_target = false)]
|
||||
public delegate int HandshakeConfirmed (Connection conn, void * user_data);
|
||||
[CCode (cname = "ngtcp2_recv_new_token", has_target = false)]
|
||||
public delegate int RecvNewToken (Connection conn, [CCode (array_length_type = "size_t")] uint8[] token, void * user_data);
|
||||
[CCode (cname = "ngtcp2_delete_crypto_aead_ctx", has_target = false)]
|
||||
public delegate void DeleteCryptoAeadCtx (Connection conn, CryptoAeadCtx aead_ctx, void * user_data);
|
||||
[CCode (cname = "ngtcp2_delete_crypto_cipher_ctx", has_target = false)]
|
||||
public delegate void DeleteCryptoCipherCtx (Connection conn, CryptoCipherCtx cipher_ctx, void * user_data);
|
||||
[CCode (cname = "ngtcp2_recv_datagram", has_target = false)]
|
||||
public delegate int RecvDatagram (Connection conn, uint32 flags, [CCode (array_length_type = "size_t")] uint8[] data,
|
||||
void * user_data);
|
||||
[CCode (cname = "ngtcp2_ack_datagram", has_target = false)]
|
||||
public delegate int AckDatagram (Connection conn, uint64 dgram_id, void * user_data);
|
||||
[CCode (cname = "ngtcp2_lost_datagram", has_target = false)]
|
||||
public delegate int LostDatagram (Connection conn, uint64 dgram_id, void * user_data);
|
||||
[CCode (cname = "ngtcp2_get_path_challenge_data", has_target = false)]
|
||||
public delegate int GetPathChallengeData (Connection conn, [CCode (array_length = false)] uint8[] data, void * user_data);
|
||||
[CCode (cname = "ngtcp2_stream_stop_sending", has_target = false)]
|
||||
public delegate int StreamStopSending (Connection conn, int64 stream_id, uint64 app_error_code, void * user_data,
|
||||
void * stream_user_data);
|
||||
[CCode (cname = "ngtcp2_version_negotiation", has_target = false)]
|
||||
public delegate int VersionNegotiation (Connection conn, uint32 version, ConnectionID client_dcid, void * user_data);
|
||||
[CCode (cname = "ngtcp2_recv_key", has_target = false)]
|
||||
public delegate int RecvKey (Connection conn, EncryptionLevel level, void * user_data);
|
||||
[CCode (cname = "ngtcp2_tls_early_data_rejected", has_target = false)]
|
||||
public delegate int TlsEarlyDataRejected (Connection conn, void * user_data);
|
||||
|
||||
[CCode (cname = "ngtcp2_settings", has_destroy_function = false)]
|
||||
public struct Settings {
|
||||
[CCode (cname = "ngtcp2_settings_default")]
|
||||
public Settings.make_default ();
|
||||
|
||||
public QlogWrite? qlog_write;
|
||||
public CongestionControlAlgorithm cc_algo;
|
||||
public Timestamp initial_ts;
|
||||
public Duration initial_rtt;
|
||||
public Printf? log_printf;
|
||||
public size_t max_tx_udp_payload_size;
|
||||
[CCode (array_length_cname = "tokenlen")]
|
||||
public uint8[]? token;
|
||||
public TokenType token_type;
|
||||
public RNGContext rand_ctx;
|
||||
public uint64 max_window;
|
||||
public uint64 max_stream_window;
|
||||
public size_t ack_thresh;
|
||||
public bool no_tx_udp_payload_size_shaping;
|
||||
public Duration handshake_timeout;
|
||||
[CCode (array_length_cname = "preferred_versionslen")]
|
||||
public ProtocolVersion[]? preferred_versions;
|
||||
[CCode (array_length_cname = "available_versionslen")]
|
||||
public ProtocolVersion[]? available_versions;
|
||||
public uint32 original_version;
|
||||
public bool no_pmtud;
|
||||
public uint32 initial_pkt_num;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_qlog_write", has_target = false)]
|
||||
public delegate void QlogWrite (void * user_data, uint32 flags, [CCode (array_length_type = "size_t")] uint8[] data);
|
||||
[CCode (cname = "ngtcp2_printf", has_target = false)]
|
||||
public delegate void Printf (void * user_data, string format, ...);
|
||||
|
||||
[CCode (cname = "ngtcp2_transport_params", has_destroy_function = false)]
|
||||
public struct TransportParams {
|
||||
[CCode (cname = "ngtcp2_transport_params_default")]
|
||||
public TransportParams.make_default ();
|
||||
|
||||
public PreferredAddress preferred_addr;
|
||||
public ConnectionID original_dcid;
|
||||
public ConnectionID initial_scid;
|
||||
public ConnectionID retry_scid;
|
||||
public uint64 initial_max_stream_data_bidi_local;
|
||||
public uint64 initial_max_stream_data_bidi_remote;
|
||||
public uint64 initial_max_stream_data_uni;
|
||||
public uint64 initial_max_data;
|
||||
public uint64 initial_max_streams_bidi;
|
||||
public uint64 initial_max_streams_uni;
|
||||
public Duration max_idle_timeout;
|
||||
public uint64 max_udp_payload_size;
|
||||
public uint64 active_connection_id_limit;
|
||||
public uint64 ack_delay_exponent;
|
||||
public Duration max_ack_delay;
|
||||
public uint64 max_datagram_frame_size;
|
||||
public bool stateless_reset_token_present;
|
||||
public bool disable_active_migration;
|
||||
public bool original_dcid_present;
|
||||
public bool initial_scid_present;
|
||||
public bool retry_scid_present;
|
||||
public bool preferred_addr_present;
|
||||
public uint8 stateless_reset_token[STATELESS_RESET_TOKENLEN];
|
||||
public bool grease_quic_bit;
|
||||
public VersionInfo version_info;
|
||||
public bool version_info_present;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_mem", has_destroy_function = false)]
|
||||
public struct MemoryAllocator {
|
||||
public void * user_data;
|
||||
public Malloc malloc;
|
||||
public Free free;
|
||||
public Calloc calloc;
|
||||
public Realloc realloc;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_malloc", has_target = false)]
|
||||
public delegate void * Malloc (size_t size, void * user_data);
|
||||
[CCode (cname = "ngtcp2_free", has_target = false)]
|
||||
public delegate void Free (void * ptr, void * user_data);
|
||||
[CCode (cname = "ngtcp2_calloc", has_target = false)]
|
||||
public delegate void * Calloc (size_t nmemb, size_t size, void * user_data);
|
||||
[CCode (cname = "ngtcp2_realloc", has_target = false)]
|
||||
public delegate void * Realloc (void * ptr, size_t size, void * user_data);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
[CCode (cheader_filename = "ngtcp2/ngtcp2_crypto.h", lower_case_cprefix = "ngtcp2_crypto_", gir_namespace = "NGTcp2Crypto", gir_version = "1.0")]
|
||||
namespace NGTcp2.Crypto {
|
||||
[CCode (cheader_filename = "ngtcp2/ngtcp2_crypto_quictls.h")]
|
||||
namespace Quictls {
|
||||
public int configure_client_context (OpenSSL.SSLContext ssl_ctx);
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_crypto_conn_ref", has_destroy_function = false)]
|
||||
public struct ConnectionRef {
|
||||
public GetConnection get_conn;
|
||||
public void * user_data;
|
||||
}
|
||||
|
||||
[CCode (cname = "ngtcp2_crypto_get_conn", has_target = false)]
|
||||
public delegate unowned Connection GetConnection (ConnectionRef conn_ref);
|
||||
|
||||
public ClientInitial client_initial_cb;
|
||||
public RecvCryptoData recv_crypto_data_cb;
|
||||
public Encrypt encrypt_cb;
|
||||
public Decrypt decrypt_cb;
|
||||
public HpMask hp_mask_cb;
|
||||
public RecvRetry recv_retry_cb;
|
||||
public UpdateKey update_key_cb;
|
||||
public DeleteCryptoAeadCtx delete_crypto_aead_ctx_cb;
|
||||
public DeleteCryptoCipherCtx delete_crypto_cipher_ctx_cb;
|
||||
public GetPathChallengeData get_path_challenge_data_cb;
|
||||
public VersionNegotiation version_negotiation_cb;
|
||||
}
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
[CCode (gir_namespace = "LWIP", gir_version = "1.0")]
|
||||
namespace LWIP {
|
||||
[CCode (cheader_filename = "lwip/tcpip.h", lower_case_cprefix = "tcpip_")]
|
||||
namespace Runtime {
|
||||
public void init (InitDoneFunc init_done);
|
||||
|
||||
[CCode (cname = "tcpip_callback")]
|
||||
public ErrorCode schedule (WorkFunc work);
|
||||
|
||||
[CCode (cname = "tcpip_init_done_fn")]
|
||||
public delegate void InitDoneFunc ();
|
||||
|
||||
[CCode (cname = "tcpip_callback_fn")]
|
||||
public delegate void WorkFunc ();
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "lwip/netif.h", cname = "struct netif", cprefix = "netif_")]
|
||||
public struct NetworkInterface {
|
||||
public static void add_noaddr (ref NetworkInterface netif, void * state, NetworkInterfaceInitFunc init,
|
||||
NetworkInterfaceInputFunc input = NetworkInterface.default_input_handler);
|
||||
|
||||
public void remove ();
|
||||
|
||||
public void set_up ();
|
||||
public void set_down ();
|
||||
|
||||
public void ip6_addr_set (int8 addr_idx, IP6Address address);
|
||||
public ErrorCode add_ip6_address (IP6Address address, int8 * chosen_index = null);
|
||||
public void ip6_addr_set_state (int8 addr_index, IP6AddressState state);
|
||||
|
||||
[CCode (cname = "netif_input")]
|
||||
public static ErrorCode default_input_handler (PacketBuffer pbuf, NetworkInterface netif);
|
||||
|
||||
public NetworkInterfaceInputFunc input;
|
||||
public NetworkInterfaceOutputIP6Func output_ip6;
|
||||
|
||||
public void * state;
|
||||
|
||||
public uint16 mtu;
|
||||
}
|
||||
|
||||
[CCode (cname = "netif_init_fn", has_target = false)]
|
||||
public delegate ErrorCode NetworkInterfaceInitFunc (NetworkInterface netif);
|
||||
|
||||
[CCode (cname = "netif_input_fn", has_target = false)]
|
||||
public delegate ErrorCode NetworkInterfaceInputFunc (PacketBuffer pbuf, NetworkInterface netif);
|
||||
|
||||
[CCode (cname = "netif_output_ip6_fn", has_target = false)]
|
||||
public delegate ErrorCode NetworkInterfaceOutputIP6Func (NetworkInterface netif, PacketBuffer pbuf, IP6Address address);
|
||||
|
||||
[CCode (cheader_filename = "lwip/ip6_addr.h", cname = "ip6_addr_t", cprefix = "ip6_addr_")]
|
||||
public struct IP6Address {
|
||||
[CCode (cname = "ip6addr_aton")]
|
||||
public static IP6Address parse (string str);
|
||||
}
|
||||
|
||||
[Flags]
|
||||
[CCode (cheader_filename = "lwip/ip6_addr.h", cname = "u8_t", cprefix = "IP6_ADDR_", has_type_id = false)]
|
||||
public enum IP6AddressState {
|
||||
INVALID,
|
||||
TENTATIVE,
|
||||
TENTATIVE_1,
|
||||
TENTATIVE_2,
|
||||
TENTATIVE_3,
|
||||
TENTATIVE_4,
|
||||
TENTATIVE_5,
|
||||
TENTATIVE_6,
|
||||
TENTATIVE_7,
|
||||
VALID,
|
||||
PREFERRED,
|
||||
DEPRECATED,
|
||||
DUPLICATED,
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "lwip/ip_addr.h", cname = "u8_t", cprefix = "IPADDR_TYPE_", has_type_id = false)]
|
||||
public enum IPAddressType {
|
||||
V4,
|
||||
V6,
|
||||
ANY,
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cheader_filename = "lwip/pbuf.h", cname = "struct pbuf", cprefix = "pbuf_")]
|
||||
public class PacketBuffer {
|
||||
public static PacketBuffer alloc (Layer layer, uint16 length, Type type);
|
||||
|
||||
public PacketBuffer? next;
|
||||
[CCode (array_length_cname = "len")]
|
||||
public uint8[] payload;
|
||||
public uint16 tot_len;
|
||||
|
||||
[CCode (array_length = false)]
|
||||
public unowned uint8[] get_contiguous (uint8[] buffer, uint16 len, uint16 offset = 0);
|
||||
|
||||
public ErrorCode take (uint8[] data);
|
||||
|
||||
[CCode (cname = "pbuf_layer", cprefix = "PBUF_", has_type_id = false)]
|
||||
public enum Layer {
|
||||
TRANSPORT,
|
||||
IP,
|
||||
LINK,
|
||||
RAW_TX,
|
||||
RAW,
|
||||
}
|
||||
|
||||
[CCode (cname = "pbuf_type", cprefix = "PBUF_", has_type_id = false)]
|
||||
public enum Type {
|
||||
RAM,
|
||||
ROM,
|
||||
REF,
|
||||
POOL,
|
||||
}
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cheader_filename = "lwip/tcp.h", cname = "struct tcp_pcb", cprefix = "tcp_")]
|
||||
public class TcpPcb {
|
||||
[CCode (cname = "tcp_new_ip_type")]
|
||||
public static unowned TcpPcb make (IPAddressType type);
|
||||
|
||||
[CCode (cname = "tcp_arg")]
|
||||
public void set_user_data (void * user_data);
|
||||
|
||||
[CCode (cname = "tcp_recv")]
|
||||
public void set_recv_callback (RecvFunc f);
|
||||
[CCode (cname = "tcp_sent")]
|
||||
public void set_sent_callback (SentFunc f);
|
||||
[CCode (cname = "tcp_err")]
|
||||
public void set_error_callback (ErrorFunc f);
|
||||
|
||||
public void nagle_disable ();
|
||||
public void nagle_enable ();
|
||||
|
||||
public void abort ();
|
||||
public ErrorCode close ();
|
||||
public ErrorCode shutdown (bool shut_rx, bool shut_tx);
|
||||
|
||||
public void bind_netif (NetworkInterface? netif);
|
||||
|
||||
public ErrorCode connect (IP6Address address, uint16 port, ConnectedFunc connected);
|
||||
|
||||
[CCode (cname = "tcp_recved")]
|
||||
public void notify_received (uint16 len);
|
||||
|
||||
[CCode (cname = "tcp_sndbuf")]
|
||||
public uint16 query_available_send_buffer_space ();
|
||||
|
||||
public ErrorCode write (uint8[] data, WriteFlags flags = 0);
|
||||
public ErrorCode output ();
|
||||
|
||||
[CCode (cname = "tcp_recv_fn", has_target = false)]
|
||||
public delegate ErrorCode RecvFunc (void * user_data, TcpPcb pcb, owned PacketBuffer? pbuf, ErrorCode err);
|
||||
|
||||
[CCode (cname = "tcp_sent_fn", has_target = false)]
|
||||
public delegate ErrorCode SentFunc (void * user_data, TcpPcb pcb, uint16 len);
|
||||
|
||||
[CCode (cname = "tcp_err_fn", has_target = false)]
|
||||
public delegate void ErrorFunc (void * user_data, ErrorCode err);
|
||||
|
||||
[CCode (cname = "tcp_connected_fn", has_target = false)]
|
||||
public delegate ErrorCode ConnectedFunc (void * user_data, TcpPcb pcb, ErrorCode err);
|
||||
|
||||
[Flags]
|
||||
[CCode (cname = "u8_t", cprefix = "TCP_WRITE_FLAG_", has_type_id = false)]
|
||||
public enum WriteFlags {
|
||||
COPY,
|
||||
MORE,
|
||||
}
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "lwip/err.h", cname = "err_t", cprefix = "ERR_", lower_case_cprefix = "err_", has_type_id = false)]
|
||||
public enum ErrorCode {
|
||||
OK,
|
||||
MEM,
|
||||
BUF,
|
||||
TIMEOUT,
|
||||
RTE,
|
||||
INPROGRESS,
|
||||
VAL,
|
||||
WOULDBLOCK,
|
||||
USE,
|
||||
ALREADY,
|
||||
ISCONN,
|
||||
CONN,
|
||||
IF,
|
||||
ABRT,
|
||||
RST,
|
||||
CLSD,
|
||||
ARG;
|
||||
|
||||
public int to_errno ();
|
||||
}
|
||||
}
|
||||
+500
-1
@@ -1 +1,500 @@
|
||||
// Placeholder to satisfy Meson assumptions.
|
||||
[CCode (lower_case_cprefix = "OPENSSL_", gir_namespace = "OpenSSL", gir_version = "1.0")]
|
||||
namespace OpenSSL {
|
||||
[Compact]
|
||||
[CCode (cname = "SSL_CTX", cprefix = "SSL_CTX_")]
|
||||
public class SSLContext {
|
||||
public SSLContext (SSLMethod meth);
|
||||
|
||||
[CCode (cname = "SSL_CTX_use_certificate")]
|
||||
public int use_certificate (X509 cert);
|
||||
[CCode (cname = "SSL_CTX_use_PrivateKey")]
|
||||
public int use_private_key (Envelope.Key key);
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "SSL", cprefix = "SSL_")]
|
||||
public class SSL {
|
||||
public SSL (SSLContext ctx);
|
||||
|
||||
public void set_app_data (void * data);
|
||||
|
||||
public void set_connect_state ();
|
||||
public void set_accept_state ();
|
||||
|
||||
public int set_alpn_protos (uint8[] protos);
|
||||
|
||||
public void set_quic_transport_version (int version);
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "SSL_METHOD", cprefix = "SSL_METHOD_", free_function = "")]
|
||||
public class SSLMethod {
|
||||
[CCode (cname = "TLS_method")]
|
||||
public static unowned SSLMethod tls ();
|
||||
[CCode (cname = "TLS_server_method")]
|
||||
public static unowned SSLMethod tls_server ();
|
||||
[CCode (cname = "TLS_client_method")]
|
||||
public static unowned SSLMethod tls_client ();
|
||||
|
||||
[CCode (cname = "DTLS_method")]
|
||||
public static unowned SSLMethod dtls ();
|
||||
[CCode (cname = "DTLS_server_method")]
|
||||
public static unowned SSLMethod dtls_server ();
|
||||
[CCode (cname = "DTLS_client_method")]
|
||||
public static unowned SSLMethod dtls_client ();
|
||||
}
|
||||
|
||||
[CCode (lower_case_cprefix = "TLSEXT_TYPE_")]
|
||||
namespace TLSExtensionType {
|
||||
public const int quic_transport_parameters;
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "X509", cprefix = "X509_")]
|
||||
public class X509 {
|
||||
public X509 ();
|
||||
|
||||
[CCode (cname = "X509_get_serialNumber")]
|
||||
public unowned ASN1.Integer get_serial_number ();
|
||||
|
||||
[CCode (cname = "X509_getm_notBefore")]
|
||||
public unowned ASN1.Time get_not_before ();
|
||||
[CCode (cname = "X509_getm_notAfter")]
|
||||
public unowned ASN1.Time get_not_after ();
|
||||
|
||||
public unowned Name get_subject_name ();
|
||||
public int set_issuer_name (Name name);
|
||||
|
||||
public int set_pubkey (Envelope.Key key);
|
||||
|
||||
public int sign_ctx (Envelope.MessageDigestContext ctx);
|
||||
|
||||
[CCode (cname = "X509_get_X509_PUBKEY")]
|
||||
public unowned X509PublicKey get_public_key ();
|
||||
|
||||
[CCode (cname = "i2d_X509_bio", instance_pos = 2)]
|
||||
public int to_der (BasicIO sink);
|
||||
|
||||
[CCode (cname = "PEM_write_bio_X509", instance_pos = 2)]
|
||||
public int to_pem (BasicIO sink);
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "X509_NAME", cprefix = "X509_NAME_")]
|
||||
public class Name {
|
||||
public int add_entry_by_txt (string field, ASN1.MultiByteStringType type, uint8[] bytes, int loc = -1, int set = 0);
|
||||
}
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "X509_PUBKEY", cprefix = "X509_PUBKEY_", free_function = "")]
|
||||
public class X509PublicKey {
|
||||
[CCode (cname = "i2d_X509_PUBKEY_bio", instance_pos = 2)]
|
||||
public int to_der (BasicIO sink);
|
||||
|
||||
[CCode (cname = "PEM_write_bio_X509_PUBKEY", instance_pos = 2)]
|
||||
public int to_pem (BasicIO sink);
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "BIO", cprefix = "BIO_")]
|
||||
public class BasicIO {
|
||||
public BasicIO (BasicIOMethod method);
|
||||
[CCode (cname = "BIO_new_mem_buf")]
|
||||
public BasicIO.from_static_memory_buffer (uint8[] buf);
|
||||
|
||||
public long get_mem_data ([CCode (array_length = false)] out unowned uint8[] data);
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "BIO_METHOD", cprefix = "BIO_METHOD_", free_function = "")]
|
||||
public class BasicIOMethod {
|
||||
[CCode (cname = "BIO_s_mem")]
|
||||
public static unowned BasicIOMethod memory ();
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "openssl/asn1.h")]
|
||||
namespace ASN1 {
|
||||
[Compact]
|
||||
[CCode (cname = "ASN1_INTEGER", cprefix = "ASN1_INTEGER_")]
|
||||
public class Integer {
|
||||
public int set_int64 (int64 v);
|
||||
public int set_uint64 (uint64 v);
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "ASN1_TIME", cprefix = "ASN1_TIME_")]
|
||||
public class Time {
|
||||
[CCode (cname = "X509_gmtime_adj")]
|
||||
public unowned Time adjust (long delta);
|
||||
}
|
||||
|
||||
[CCode (cname = "int", cprefix = "MBSTRING_", has_type_id = false)]
|
||||
public enum MultiByteStringType {
|
||||
UTF8,
|
||||
[CCode (cname = "MBSTRING_ASC")]
|
||||
ASCII,
|
||||
}
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "openssl/evp.h")]
|
||||
namespace Envelope {
|
||||
[Compact]
|
||||
[CCode (cname = "EVP_PKEY_CTX", cprefix = "EVP_PKEY_", free_function = "EVP_PKEY_CTX_free")]
|
||||
public class KeyContext {
|
||||
[CCode (cname = "EVP_PKEY_CTX_new")]
|
||||
public KeyContext.for_key (Key key, Engine? engine = null);
|
||||
[CCode (cname = "EVP_PKEY_CTX_new_id")]
|
||||
public KeyContext.for_key_type (KeyType type, Engine? engine = null);
|
||||
|
||||
public int keygen_init ();
|
||||
public int keygen (ref Key pkey);
|
||||
|
||||
public int derive_init ();
|
||||
public int derive_set_peer (Key peer);
|
||||
public int derive ([CCode (array_length = false)] uint8[]? key, ref size_t keylen);
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "EVP_PKEY", cprefix = "EVP_PKEY_", copy_function = "EVP_PKEY_dup")]
|
||||
public class Key {
|
||||
[CCode (cname = "d2i_PUBKEY_bio")]
|
||||
public Key.from_der (BasicIO source, Key ** a = null);
|
||||
[CCode (cname = "EVP_PKEY_new_raw_public_key")]
|
||||
public Key.from_raw_public_key (KeyType type, Engine? engine, uint8[] pub);
|
||||
[CCode (cname = "EVP_PKEY_new_raw_private_key")]
|
||||
public Key.from_raw_private_key (KeyType type, Engine? engine, uint8[] priv);
|
||||
|
||||
public int get_raw_public_key ([CCode (array_length = false)] uint8[]? pub, ref size_t len);
|
||||
public int get_raw_private_key ([CCode (array_length = false)] uint8[]? priv, ref size_t len);
|
||||
|
||||
[CCode (cname = "i2d_PUBKEY_bio", instance_pos = 2)]
|
||||
public int to_der (BasicIO sink);
|
||||
|
||||
[CCode (cname = "PEM_write_bio_PUBKEY", instance_pos = 2)]
|
||||
public int to_pem (BasicIO sink);
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "EVP_PKEY_CTX", cprefix = "EVP_PKEY_CTX_")]
|
||||
public class PublicKeyContext {
|
||||
}
|
||||
|
||||
[CCode (cname = "int", cprefix = "EVP_PKEY_", has_type_id = false)]
|
||||
public enum KeyType {
|
||||
NONE,
|
||||
RSA,
|
||||
RSA2,
|
||||
RSA_PSS,
|
||||
DSA,
|
||||
DSA1,
|
||||
DSA2,
|
||||
DSA3,
|
||||
DSA4,
|
||||
DH,
|
||||
DHX,
|
||||
EC,
|
||||
SM2,
|
||||
HMAC,
|
||||
CMAC,
|
||||
SCRYPT,
|
||||
TLS1_PRF,
|
||||
HKDF,
|
||||
POLY1305,
|
||||
SIPHASH,
|
||||
X25519,
|
||||
ED25519,
|
||||
X448,
|
||||
ED448,
|
||||
KEYMGMT,
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cheader_filename = "openssl/kdf.h", cname = "EVP_KDF", cprefix = "EVP_KDF_")]
|
||||
public class KeyDerivationFunction {
|
||||
public static KeyDerivationFunction? fetch (LibraryContext? ctx, string algorithm, string? properties = null);
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cheader_filename = "openssl/kdf.h", cname = "EVP_KDF_CTX", cprefix = "EVP_KDF_",
|
||||
free_function = "EVP_KDF_CTX_free")]
|
||||
public class KeyDerivationContext {
|
||||
[CCode (cname = "EVP_KDF_CTX_new")]
|
||||
public KeyDerivationContext (KeyDerivationFunction kdf);
|
||||
|
||||
public int derive (uint8[] key, [CCode (array_length = false)] Param[] params);
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "openssl/core_names.h", lower_case_cprefix = "OSSL_KDF_NAME_")]
|
||||
namespace KeyDerivationAlgorithm {
|
||||
public const string HKDF;
|
||||
public const string TLS1_3_KDF;
|
||||
public const string PBKDF1;
|
||||
public const string PBKDF2;
|
||||
public const string SCRYPT;
|
||||
public const string SSHKDF;
|
||||
public const string SSKDF;
|
||||
public const string TLS1_PRF;
|
||||
public const string X942KDF_ASN1;
|
||||
public const string X942KDF_CONCAT;
|
||||
public const string X963KDF;
|
||||
public const string KBKDF;
|
||||
public const string KRB5KDF;
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "openssl/core_names.h", lower_case_cprefix = "OSSL_KDF_PARAM_")]
|
||||
namespace KeyDerivationParameter {
|
||||
public const string SECRET;
|
||||
public const string KEY;
|
||||
public const string SALT;
|
||||
public const string PASSWORD;
|
||||
public const string PREFIX;
|
||||
public const string LABEL;
|
||||
public const string DATA;
|
||||
public const string DIGEST;
|
||||
public const string CIPHER;
|
||||
public const string MAC;
|
||||
public const string MAC_SIZE;
|
||||
public const string PROPERTIES;
|
||||
public const string ITER;
|
||||
public const string MODE;
|
||||
public const string PKCS5;
|
||||
public const string UKM;
|
||||
public const string CEK_ALG;
|
||||
public const string SCRYPT_N;
|
||||
public const string SCRYPT_R;
|
||||
public const string SCRYPT_P;
|
||||
public const string SCRYPT_MAXMEM;
|
||||
public const string INFO;
|
||||
public const string SEED;
|
||||
public const string SSHKDF_XCGHASH;
|
||||
public const string SSHKDF_SESSION_ID;
|
||||
public const string SSHKDF_TYPE;
|
||||
public const string SIZE;
|
||||
public const string CONSTANT;
|
||||
public const string PKCS12_ID;
|
||||
public const string KBKDF_USE_L;
|
||||
public const string KBKDF_USE_SEPARATOR;
|
||||
public const string X942_ACVPINFO;
|
||||
public const string X942_PARTYUINFO;
|
||||
public const string X942_PARTYVINFO;
|
||||
public const string X942_SUPP_PUBINFO;
|
||||
public const string X942_SUPP_PRIVINFO;
|
||||
public const string X942_USE_KEYBITS;
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "EVP_CIPHER_CTX", cprefix = "EVP_CIPHER_CTX_")]
|
||||
public class CipherContext {
|
||||
public CipherContext ();
|
||||
|
||||
public int reset ();
|
||||
|
||||
public int ctrl (CipherCtrlType type, int arg, void * ptr);
|
||||
|
||||
[CCode (cname = "EVP_EncryptInit")]
|
||||
public int encrypt_init (Cipher cipher,
|
||||
[CCode (array_length = false)] uint8[] key,
|
||||
[CCode (array_length = false)] uint8[] iv);
|
||||
[CCode (cname = "EVP_EncryptUpdate")]
|
||||
public int encrypt_update ([CCode (array_length = false)] uint8[] output, ref int outlen, uint8[] input);
|
||||
[CCode (cname = "EVP_EncryptFinal")]
|
||||
public int encrypt_final ([CCode (array_length = false)] uint8[] output, ref int outlen);
|
||||
|
||||
[CCode (cname = "EVP_DecryptInit")]
|
||||
public int decrypt_init (Cipher cipher,
|
||||
[CCode (array_length = false)] uint8[] key,
|
||||
[CCode (array_length = false)] uint8[] iv);
|
||||
[CCode (cname = "EVP_DecryptUpdate")]
|
||||
public int decrypt_update ([CCode (array_length = false)] uint8[] output, ref int outlen, uint8[] input);
|
||||
[CCode (cname = "EVP_DecryptFinal")]
|
||||
public int decrypt_final ([CCode (array_length = false)] uint8[] output, ref int outlen);
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "EVP_CIPHER", cprefix = "EVP_CIPHER_")]
|
||||
public class Cipher {
|
||||
public static Cipher? fetch (LibraryContext? ctx, string algorithm, string? properties = null);
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "openssl/evp.h", cname = "int", cprefix = "EVP_CTRL_", has_type_id = false)]
|
||||
public enum CipherCtrlType {
|
||||
INIT,
|
||||
SET_KEY_LENGTH,
|
||||
GET_RC2_KEY_BITS,
|
||||
SET_RC2_KEY_BITS,
|
||||
GET_RC5_ROUNDS,
|
||||
SET_RC5_ROUNDS,
|
||||
RAND_KEY,
|
||||
PBE_PRF_NID,
|
||||
COPY,
|
||||
AEAD_SET_IVLEN,
|
||||
AEAD_GET_TAG,
|
||||
AEAD_SET_TAG,
|
||||
AEAD_SET_IV_FIXED,
|
||||
GCM_SET_IVLEN,
|
||||
GCM_GET_TAG,
|
||||
GCM_SET_TAG,
|
||||
GCM_SET_IV_FIXED,
|
||||
GCM_IV_GEN,
|
||||
CCM_SET_IVLEN,
|
||||
CCM_GET_TAG,
|
||||
CCM_SET_TAG,
|
||||
CCM_SET_IV_FIXED,
|
||||
CCM_SET_L,
|
||||
CCM_SET_MSGLEN,
|
||||
AEAD_TLS1_AAD,
|
||||
AEAD_SET_MAC_KEY,
|
||||
GCM_SET_IV_INV,
|
||||
TLS1_1_MULTIBLOCK_AAD,
|
||||
TLS1_1_MULTIBLOCK_ENCRYPT,
|
||||
TLS1_1_MULTIBLOCK_DECRYPT,
|
||||
TLS1_1_MULTIBLOCK_MAX_BUFSIZE,
|
||||
SSL3_MASTER_SECRET,
|
||||
SET_SBOX,
|
||||
SBOX_USED,
|
||||
KEY_MESH,
|
||||
BLOCK_PADDING_MODE,
|
||||
SET_PIPELINE_OUTPUT_BUFS,
|
||||
SET_PIPELINE_INPUT_BUFS,
|
||||
SET_PIPELINE_INPUT_LENS,
|
||||
GET_IVLEN,
|
||||
SET_SPEED,
|
||||
PROCESS_UNPROTECTED,
|
||||
GET_WRAP_CIPHER,
|
||||
TLSTREE,
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "EVP_MD_CTX", cprefix = "EVP_MD_CTX_")]
|
||||
public class MessageDigestContext {
|
||||
public MessageDigestContext ();
|
||||
|
||||
[CCode (cname = "EVP_DigestSignInit")]
|
||||
public int digest_sign_init (PublicKeyContext ** pctx, MessageDigest? type, Engine? engine = null, Key? key = null);
|
||||
[CCode (cname = "EVP_DigestSignUpdate")]
|
||||
public int digest_sign_update (uint8[] data);
|
||||
[CCode (cname = "EVP_DigestSignFinal")]
|
||||
public int digest_sign_final ([CCode (array_length = false)] uint8[]? sigret, ref size_t siglen);
|
||||
[CCode (cname = "EVP_DigestSign")]
|
||||
public int digest_sign ([CCode (array_length = false)] uint8[]? sigret, ref size_t siglen, uint8[] tbs);
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "EVP_MD", cprefix = "EVP_MD_")]
|
||||
public class MessageDigest {
|
||||
public static MessageDigest fetch (LibraryContext? ctx, string algorithm, string? properties = null);
|
||||
}
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cheader_filename = "openssl/engine.h", cname = "ENGINE")]
|
||||
public class Engine {
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cheader_filename = "openssl/types.h", cname = "OSSL_LIB_CTX")]
|
||||
public class LibraryContext {
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "openssl/core.h", cname = "OSSL_PARAM", has_copy_function = false, has_destroy_function = false)]
|
||||
public struct Param {
|
||||
public unowned string? key;
|
||||
public ParamDataType data_type;
|
||||
[CCode (array_length_cname = "data_size")]
|
||||
public unowned uint8[]? data;
|
||||
public size_t return_size;
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "openssl/core.h", cname = "guint", cprefix = "OSSL_PARAM_", has_type_id = false)]
|
||||
public enum ParamDataType {
|
||||
INTEGER,
|
||||
UNSIGNED_INTEGER,
|
||||
REAL,
|
||||
UTF8_STRING,
|
||||
OCTET_STRING,
|
||||
UTF8_PTR,
|
||||
OCTET_PTR,
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "openssl/core.h", cname = "size_t", cprefix = "OSSL_PARAM_", has_type_id = false)]
|
||||
public enum ParamReturnSize {
|
||||
UNMODIFIED,
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "openssl/objects.h", lower_case_cprefix = "SN_")]
|
||||
namespace ShortName {
|
||||
public const string sha256;
|
||||
public const string sha384;
|
||||
public const string sha512;
|
||||
public const string chacha20_poly1305;
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "openssl/rand.h")]
|
||||
namespace Rng {
|
||||
[CCode (cname = "RAND_bytes")]
|
||||
public int generate (uint8[] buf);
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "BN_CTX", cprefix = "BN_CTX_")]
|
||||
public class BigNumberContext {
|
||||
[CCode (cname = "BN_CTX_secure_new")]
|
||||
public BigNumberContext.secure ();
|
||||
}
|
||||
|
||||
[Compact]
|
||||
[CCode (cname = "BIGNUM", cprefix = "BN_")]
|
||||
public class BigNumber {
|
||||
public BigNumber ();
|
||||
[CCode (cname = "BN_native2bn")]
|
||||
public BigNumber.from_native (uint8[] data, BigNumber * ret = null);
|
||||
[CCode (cname = "BN_bin2bn")]
|
||||
public BigNumber.from_big_endian (uint8[] data, BigNumber * ret = null);
|
||||
|
||||
public static BigNumber get_rfc2409_prime_768 (BigNumber * ret = null);
|
||||
public static BigNumber get_rfc2409_prime_1024 (BigNumber * ret = null);
|
||||
|
||||
public static BigNumber get_rfc3526_prime_1536 (BigNumber * ret = null);
|
||||
public static BigNumber get_rfc3526_prime_2048 (BigNumber * ret = null);
|
||||
public static BigNumber get_rfc3526_prime_3072 (BigNumber * ret = null);
|
||||
public static BigNumber get_rfc3526_prime_4096 (BigNumber * ret = null);
|
||||
public static BigNumber get_rfc3526_prime_6144 (BigNumber * ret = null);
|
||||
public static BigNumber get_rfc3526_prime_8192 (BigNumber * ret = null);
|
||||
|
||||
public bool is_zero ();
|
||||
|
||||
public static int add (BigNumber r, BigNumber a, BigNumber b);
|
||||
public static int sub (BigNumber r, BigNumber a, BigNumber b);
|
||||
public static int mul (BigNumber r, BigNumber a, BigNumber b, BigNumberContext ctx);
|
||||
public static int mod (BigNumber rem, BigNumber m, BigNumber d, BigNumberContext ctx);
|
||||
public static int mod_exp (BigNumber r, BigNumber a, BigNumber p, BigNumber m, BigNumberContext ctx);
|
||||
|
||||
public int num_bits ();
|
||||
public int num_bytes ();
|
||||
|
||||
[CCode (cname = "BN_bn2bin")]
|
||||
public int to_big_endian ([CCode (array_length = false)] uint8[] to);
|
||||
|
||||
[CCode (cname = "BN_bn2binpad")]
|
||||
public int to_big_endian_padded (uint8[] to);
|
||||
|
||||
[CCode (cname = "BN_bn2dec")]
|
||||
public char * to_string ();
|
||||
|
||||
[CCode (cname = "BN_bn2hex")]
|
||||
public char * to_hex_string ();
|
||||
}
|
||||
|
||||
[CCode (cheader_filename = "openssl/crypto.h", lower_case_cprefix = "CRYPTO_")]
|
||||
namespace Crypto {
|
||||
public int memcmp (void * a, void * b, size_t len);
|
||||
}
|
||||
|
||||
[CCode (lower_case_cprefix = "ERR_")]
|
||||
namespace Error {
|
||||
public ulong get_error ();
|
||||
public void error_string_n (ulong e, char[] buf);
|
||||
}
|
||||
|
||||
public void free (void * addr);
|
||||
}
|
||||
Reference in new issue
Block a user