frida 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CODE_OF_CONDUCT.md +84 -0
  3. data/Gemfile +12 -0
  4. data/Gemfile.lock +25 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +64 -0
  7. data/Rakefile +20 -0
  8. data/exe/frida +3 -0
  9. data/ext/c_frida/Application.c +79 -0
  10. data/ext/c_frida/Bus.c +91 -0
  11. data/ext/c_frida/Child.c +134 -0
  12. data/ext/c_frida/Compiler.c +208 -0
  13. data/ext/c_frida/Crash.c +92 -0
  14. data/ext/c_frida/Device.c +955 -0
  15. data/ext/c_frida/DeviceManager.c +260 -0
  16. data/ext/c_frida/EndpointParameters.c +189 -0
  17. data/ext/c_frida/FileMonitor.c +67 -0
  18. data/ext/c_frida/GObject.c +138 -0
  19. data/ext/c_frida/IOStream.c +228 -0
  20. data/ext/c_frida/PortalMembership.c +43 -0
  21. data/ext/c_frida/PortalService.c +413 -0
  22. data/ext/c_frida/Process.c +67 -0
  23. data/ext/c_frida/Relay.c +121 -0
  24. data/ext/c_frida/Script.c +221 -0
  25. data/ext/c_frida/Session.c +626 -0
  26. data/ext/c_frida/Spawn.c +53 -0
  27. data/ext/c_frida/c_frida.c +68 -0
  28. data/ext/c_frida/extconf.rb +26 -25
  29. data/ext/c_frida/gutils.c +498 -0
  30. data/ext/c_frida/gvl_bridge.c +131 -0
  31. data/ext/c_frida/inc/Application.h +9 -0
  32. data/ext/c_frida/inc/Bus.h +15 -0
  33. data/ext/c_frida/inc/Child.h +9 -0
  34. data/ext/c_frida/inc/Compiler.h +21 -0
  35. data/ext/c_frida/inc/Crash.h +9 -0
  36. data/ext/c_frida/inc/Device.h +71 -0
  37. data/ext/c_frida/inc/DeviceManager.h +20 -0
  38. data/ext/c_frida/inc/EndpointParameters.h +15 -0
  39. data/ext/c_frida/inc/FileMonitor.h +9 -0
  40. data/ext/c_frida/inc/GObject.h +10 -0
  41. data/ext/c_frida/inc/IOStream.h +29 -0
  42. data/ext/c_frida/inc/PortalMembership.h +9 -0
  43. data/ext/c_frida/inc/PortalService.h +47 -0
  44. data/ext/c_frida/inc/Process.h +9 -0
  45. data/ext/c_frida/inc/Relay.h +9 -0
  46. data/ext/c_frida/inc/Script.h +21 -0
  47. data/ext/c_frida/inc/Session.h +40 -0
  48. data/ext/c_frida/inc/Spawn.h +9 -0
  49. data/ext/c_frida/inc/c_frida.h +129 -0
  50. data/ext/c_frida/inc/gutils.h +21 -0
  51. data/ext/c_frida/inc/gvl_bridge.h +42 -0
  52. data/frida.gemspec +39 -0
  53. data/lib/frida/version.rb +5 -0
  54. data/lib/frida.rb +8 -0
  55. metadata +55 -3
@@ -0,0 +1,68 @@
1
+ #include "c_frida.h"
2
+
3
+ VALUE _gvl_bridge_thread;
4
+
5
+ VALUE mCFrida;
6
+ VALUE cGObject;
7
+ VALUE cDevice;
8
+ VALUE cDeviceManager;
9
+ VALUE cBus;
10
+ VALUE cIOStream;
11
+ VALUE cApplication;
12
+ VALUE cProcess;
13
+ VALUE cSpawn;
14
+ VALUE cChild;
15
+ VALUE cSession;
16
+ VALUE cScript;
17
+ VALUE cRelay;
18
+ VALUE cPortalMembership;
19
+ VALUE cCrash;
20
+ VALUE cFileMonitor;
21
+ VALUE cCompiler;
22
+ VALUE cEndpointParameters;
23
+ VALUE cPortalService;
24
+
25
+ void raise_argerror(char *err)
26
+ {
27
+ rb_raise(rb_eArgError, "%s", err);
28
+ }
29
+
30
+ void raise_rerror(char *err, GError *gerr)
31
+ {
32
+ if (!gerr)
33
+ rb_raise(rb_eRuntimeError, "%s", err);
34
+ else if (gerr->message) {
35
+ VALUE ruby_string = rb_str_new_cstr(gerr->message);
36
+ rb_funcall(ruby_string, rb_intern("force_encoding"), 1, rb_const_get(rb_cEncoding, rb_intern("UTF_8")));
37
+ rb_funcall(rb_mKernel, rb_intern("raise"), 2, rb_eRuntimeError, ruby_string);
38
+ g_error_free(gerr);
39
+ } else
40
+ raise_rerror("error.", NULL);
41
+ }
42
+
43
+ void Init_c_frida(void)
44
+ {
45
+ rb_require("date");
46
+ mCFrida = rb_define_module("CFrida");
47
+ frida_init();
48
+ rb_define_const(mCFrida, "FRIDA_VERSION", rb_str_new_cstr(frida_version_string()));
49
+ define_GObject();
50
+ define_Device();
51
+ define_DeviceManager();
52
+ define_Bus();
53
+ define_IOStream();
54
+ define_Application();
55
+ define_Process();
56
+ define_Spawn();
57
+ define_Child();
58
+ define_Session();
59
+ define_Script();
60
+ define_Relay();
61
+ define_PortalMembership();
62
+ define_Crash();
63
+ define_FileMonitor();
64
+ define_Compiler();
65
+ define_EndpointParameters();
66
+ define_PortalService();
67
+ _gvl_bridge_thread = rb_thread_create(RUBY_METHOD_FUNC(gvl_bridge), NULL);
68
+ }
@@ -1,25 +1,26 @@
1
- # frozen_string_literal: true
2
-
3
- require "mkmf"
4
-
5
- unless ENV["FRIDA_CORE_DEVKIT"] && File.directory?(ENV["FRIDA_CORE_DEVKIT"])
6
- abort "please download frida-core devkit, and set its path in the env variable FRIDA_CORE_DEVKIT"
7
- end
8
-
9
- # todo: use the native #have_header and #have_library
10
- unless File.file?("#{ENV["FRIDA_CORE_DEVKIT"]}/frida-core.h") && File.file?("#{ENV["FRIDA_CORE_DEVKIT"]}/libfrida-core.a")
11
- abort "could not find frida-core.h or libfrida-core.a in the configured env variable FRIDA_CORE_DEVKIT"
12
- end
13
-
14
- W =
15
- if false
16
- # only on DEV mode because it detects lot of unused var/params, in our code and Ruby's.
17
- "-Wno-error=cast-function-type -Wno-error=unused-parameter -Wno-error=unused-variable -Wno-error=unused-function -Wall -Werror -Wextra"
18
- else
19
- ""
20
- end
21
-
22
- $CFLAGS = "#{W} -g3 -ffunction-sections -fdata-sections -I#{ENV["FRIDA_CORE_DEVKIT"]} -I#{File.dirname(__FILE__)}/inc"
23
- $LDFLAGS = "-Wl,--export-dynamic -static-libgcc -Wl,-z,noexecstack,--gc-sections -L#{ENV["FRIDA_CORE_DEVKIT"]} -lfrida-core -ldl -lrt -lm -lresolv -pthread"
24
-
25
- create_makefile("c_frida")
1
+ # frozen_string_literal: true
2
+ require "mkmf"
3
+
4
+ unless ENV["FRIDA_CORE_DEVKIT"] && File.directory?(ENV["FRIDA_CORE_DEVKIT"])
5
+ abort "please download frida-core devkit, and set its path in the env variable FRIDA_CORE_DEVKIT"
6
+ end
7
+
8
+ # todo: use the native #have_header and #have_library
9
+ unless File.file?("#{ENV["FRIDA_CORE_DEVKIT"]}/frida-core.h") && File.file?("#{ENV["FRIDA_CORE_DEVKIT"]}/libfrida-core.a")
10
+ abort "could not find frida-core.h or libfrida-core.a in the configured env variable FRIDA_CORE_DEVKIT"
11
+ end
12
+
13
+ if RUBY_PLATFORM =~ /darwin/ && RUBY_PLATFORM =~ /x86_64/
14
+ target = "x86_64-apple-macos10.9"
15
+ $CFLAGS << " -I#{ENV["FRIDA_CORE_DEVKIT"]} -I#{File.dirname(__FILE__)}/inc"
16
+ $CFLAGS << " -target #{target} -w"
17
+ $libs << " -L. -L#{ENV["FRIDA_CORE_DEVKIT"]} -lfrida-core -lbsm -ldl -lm -lresolv"
18
+ $LDFLAGS << " -Wl,-framework,Foundation,-framework,AppKit,-dead_strip"
19
+ elsif RUBY_PLATFORM =~ /linux/
20
+ $CFLAGS = "-g3 -ffunction-sections -fdata-sections -I#{ENV["FRIDA_CORE_DEVKIT"]} -I#{File.dirname(__FILE__)}/inc"
21
+ $LDFLAGS = "-Wl,--export-dynamic -static-libgcc -Wl,-z,noexecstack,--gc-sections -L#{ENV["FRIDA_CORE_DEVKIT"]} -lfrida-core -ldl -lrt -lm -lresolv -pthread"
22
+ else
23
+ abort "Platform not supported."
24
+ end
25
+
26
+ create_makefile("c_frida")
@@ -0,0 +1,498 @@
1
+ #include "gutils.h"
2
+
3
+ // Ruby version of frida-python's Glib objects un/marshals.
4
+ VALUE rbGObject_marshal_string(const gchar * str)
5
+ {
6
+ if (!str)
7
+ return (Qnil);
8
+ return (rb_str_new_cstr(str));
9
+ }
10
+
11
+ gboolean rbGObject_unmarshal_string(VALUE value, gchar **str)
12
+ {
13
+ VALUE to_s = rb_funcall(value, rb_intern("to_s"), 0);
14
+ *str = g_strdup(StringValueCStr(to_s));
15
+ return (*str != NULL);
16
+ }
17
+
18
+ VALUE rbGObject_marshal_enum(gint value, GType type)
19
+ {
20
+ GEnumClass * enum_class;
21
+ GEnumValue * enum_value;
22
+ VALUE result;
23
+
24
+ enum_class = g_type_class_ref (type);
25
+
26
+ enum_value = g_enum_get_value (enum_class, value);
27
+ g_assert (enum_value != NULL);
28
+
29
+ result = rbGObject_marshal_string(enum_value->value_nick);
30
+
31
+ g_type_class_unref (enum_class);
32
+
33
+ return (result);
34
+ }
35
+
36
+ VALUE rbGObject_marshal_variant(GVariant * variant)
37
+ {
38
+ if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING))
39
+ return rbGObject_marshal_string(g_variant_get_string(variant, NULL));
40
+
41
+ if (g_variant_is_of_type(variant, G_VARIANT_TYPE_INT64))
42
+ return LL2NUM(g_variant_get_int64(variant));
43
+
44
+ if (g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN))
45
+ return (g_variant_get_boolean(variant) ? Qtrue : Qfalse);
46
+
47
+ if (g_variant_is_of_type(variant, G_VARIANT_TYPE("ay"))) {
48
+ gconstpointer elements;
49
+ gsize n_elements;
50
+
51
+ elements = g_variant_get_fixed_array(variant, &n_elements, sizeof(guint8));
52
+
53
+ return rb_str_new(elements, n_elements);
54
+ }
55
+
56
+ if (g_variant_is_of_type(variant, G_VARIANT_TYPE_VARDICT)) {
57
+ VALUE hash;
58
+ GVariantIter iter;
59
+ gchar * key;
60
+ GVariant * raw_value;
61
+
62
+ hash = rb_hash_new();
63
+
64
+ g_variant_iter_init (&iter, variant);
65
+
66
+ while (g_variant_iter_next(&iter, "{sv}", &key, &raw_value)) {
67
+ rb_hash_aset(hash, ID2SYM(rb_intern(key)), rbGObject_marshal_variant(raw_value));
68
+ g_variant_unref(raw_value);
69
+ g_free (key);
70
+ }
71
+ return hash;
72
+ }
73
+
74
+ if (g_variant_is_of_type (variant, G_VARIANT_TYPE_ARRAY)) {
75
+ GVariantIter iter;
76
+ VALUE list;
77
+ guint i;
78
+ GVariant * child;
79
+
80
+ g_variant_iter_init (&iter, variant);
81
+
82
+ list = rb_ary_new_capa(g_variant_iter_n_children(&iter));
83
+
84
+ for (i = 0; (child = g_variant_iter_next_value (&iter)) != NULL; i++) {
85
+ rb_ary_store(list, i, rbGObject_marshal_variant(child));
86
+ g_variant_unref (child);
87
+ }
88
+ return list;
89
+ }
90
+ return (Qnil);
91
+ }
92
+
93
+ gboolean rbGObject_unmarshal_certificate(const gchar *str, GTlsCertificate **certificate)
94
+ {
95
+ GError * error = NULL;
96
+
97
+ if (strchr(str, '\n') != NULL)
98
+ *certificate = g_tls_certificate_new_from_pem(str, -1, &error);
99
+ else
100
+ *certificate = g_tls_certificate_new_from_file(str, &error);
101
+ if (error != NULL)
102
+ goto propagate_error;
103
+
104
+ return TRUE;
105
+
106
+ propagate_error: {
107
+ raise_rerror(NULL, error);
108
+
109
+ return FALSE;
110
+ }
111
+ }
112
+
113
+ VALUE rbGObject_marshal_dict(GHashTable *dict)
114
+ {
115
+ VALUE result;
116
+ GHashTableIter iter;
117
+ const gchar * key;
118
+ GVariant * raw_value;
119
+
120
+ result = rb_hash_new();
121
+
122
+ g_hash_table_iter_init(&iter, dict);
123
+ while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &raw_value)) {
124
+ rb_hash_aset(result, ID2SYM(rb_intern(key)), rbGObject_marshal_variant(raw_value));
125
+ }
126
+ return result;
127
+ }
128
+
129
+ gboolean rbGObject_unmarshal_enum(const gchar *str, GType type, gpointer value)
130
+ {
131
+ GEnumClass * enum_class;
132
+ GEnumValue * enum_value;
133
+
134
+ enum_class = g_type_class_ref(type);
135
+
136
+ enum_value = g_enum_get_value_by_nick(enum_class, str);
137
+ if (enum_value == NULL)
138
+ goto invalid_value;
139
+
140
+ *((gint *) value) = enum_value->value;
141
+
142
+ g_type_class_unref(enum_class);
143
+
144
+ return TRUE;
145
+
146
+ invalid_value: {
147
+ return FALSE;
148
+ }
149
+ }
150
+
151
+ static VALUE rbGObject_marshal_datetime(const gchar * iso8601_text)
152
+ {
153
+ VALUE result;
154
+ GDateTime * raw_dt, * dt;
155
+
156
+ raw_dt = g_date_time_new_from_iso8601(iso8601_text, NULL);
157
+ if (raw_dt == NULL)
158
+ return (Qnil);
159
+
160
+ dt = g_date_time_to_local (raw_dt);
161
+ result = rb_funcall(rb_const_get(rb_cObject, rb_intern("DateTime")), rb_intern("new"), 7,
162
+ LL2NUM(g_date_time_get_year(dt)),
163
+ LL2NUM(g_date_time_get_month(dt)),
164
+ LL2NUM(g_date_time_get_day_of_month(dt)),
165
+ LL2NUM(g_date_time_get_hour(dt)),
166
+ LL2NUM(g_date_time_get_minute(dt)),
167
+ LL2NUM(g_date_time_get_second(dt)),
168
+ LL2NUM(g_date_time_get_microsecond(dt)));
169
+
170
+ g_date_time_unref(dt);
171
+ g_date_time_unref(raw_dt);
172
+
173
+ return result;
174
+ }
175
+
176
+ VALUE rbApplication_marshal_parameters_dict(GHashTable * dict)
177
+ {
178
+ VALUE result;
179
+ GHashTableIter iter;
180
+ const gchar * key;
181
+ GVariant * raw_value;
182
+
183
+ result = rb_hash_new();
184
+
185
+ g_hash_table_iter_init(&iter, dict);
186
+
187
+ while (g_hash_table_iter_next(&iter, (gpointer *)&key, (gpointer *)&raw_value)) {
188
+ VALUE value;
189
+
190
+ if (strcmp(key, "started") == 0 && g_variant_is_of_type(raw_value, G_VARIANT_TYPE_STRING))
191
+ value = rbGObject_marshal_datetime(g_variant_get_string (raw_value, NULL));
192
+ else
193
+ value = rbGObject_marshal_variant(raw_value);
194
+
195
+ rb_hash_aset(result, ID2SYM(rb_intern(key)), value);
196
+ }
197
+
198
+ return result;
199
+ }
200
+
201
+ gboolean rbGObject_unmarshal_strv(VALUE value, gchar ***strv, gint *length)
202
+ {
203
+ gint n, i;
204
+ gchar ** elements;
205
+
206
+ n = RARRAY_LEN(value);
207
+ elements = g_new0(gchar *, n + 1);
208
+
209
+ for (i = 0; i != n; i++) {
210
+ VALUE element;
211
+
212
+ element = RARRAY_AREF(value, i);
213
+ elements[i] = g_strdup(StringValueCStr(element));
214
+ if (elements[i] == NULL)
215
+ goto invalid_element;
216
+ }
217
+
218
+ *strv = elements;
219
+ *length = n;
220
+
221
+ return TRUE;
222
+
223
+ invalid_element: {
224
+ g_strfreev(elements);
225
+ return FALSE;
226
+ }
227
+ }
228
+
229
+ gboolean rbGObject_unmarshal_envp(VALUE hash, gchar ***envp, gint *length)
230
+ {
231
+ gint n;
232
+ gchar **elements;
233
+ VALUE keys, name, value;
234
+ gchar *raw_name = NULL;
235
+ gchar *raw_value = NULL;
236
+
237
+ keys = rb_funcall(hash, rb_intern("keys"), 0);
238
+ n = RARRAY_LEN(hash);
239
+ elements = g_new0 (gchar *, n + 1);
240
+
241
+ for (int i = 0; i < n; i++) {
242
+ name = RARRAY_AREF(keys, i);
243
+ raw_name = g_strdup(StringValueCStr(name));
244
+ value = rb_hash_aref(hash, name);
245
+ raw_value = g_strdup(StringValueCStr(value));
246
+ elements[i] = g_strconcat (raw_name, "=", raw_value, NULL);
247
+
248
+ g_free(g_steal_pointer(&raw_value));
249
+ g_free(g_steal_pointer(&raw_name));
250
+ }
251
+
252
+ *envp = elements;
253
+ *length = n;
254
+
255
+ return TRUE;
256
+ }
257
+
258
+ gboolean rbGObject_unmarshal_variant(VALUE value, GVariant ** variant)
259
+ {
260
+ if (RB_TYPE_P(value, T_STRING)) {
261
+ gchar *str;
262
+
263
+ rbGObject_unmarshal_string(value, &str);
264
+
265
+ *variant = g_variant_new_take_string(str);
266
+ } else if (value == Qtrue || value == Qfalse) {
267
+ *variant = g_variant_new_boolean(value == Qtrue);
268
+ } else if (RB_TYPE_P(value, T_FIXNUM)) {
269
+ long long l;
270
+
271
+ l = NUM2LL(value);
272
+ *variant = g_variant_new_int64(l);
273
+ } else {
274
+ goto unsupported_type;
275
+ }
276
+ return TRUE;
277
+
278
+ unsupported_type: {
279
+ raise_argerror("unsupported type");
280
+ goto propagate_error;
281
+ }
282
+ propagate_error: {
283
+ return FALSE;
284
+ }
285
+ }
286
+
287
+ VALUE rbGObject_marshal_strv(gchar **strv, gint length)
288
+ {
289
+ VALUE result;
290
+ gint i;
291
+
292
+ if (strv == NULL)
293
+ return (Qnil);
294
+
295
+ result = rb_ary_new_capa(length);
296
+ for (i = 0; i != length; i++) {
297
+ rb_ary_store(result, i, rbGObject_marshal_string(strv[i]));
298
+ }
299
+
300
+ return result;
301
+ }
302
+
303
+ VALUE rbGObject_marshal_envp(const gchar **envp, gint length)
304
+ {
305
+ VALUE result;
306
+ gint i;
307
+
308
+ if (envp == NULL)
309
+ return (Qnil);
310
+
311
+ result = rb_hash_new();
312
+
313
+ for (i = 0; i != length; i++) {
314
+ gchar **tokens;
315
+
316
+ tokens = g_strsplit(envp[i], "=", 2);
317
+
318
+ if (g_strv_length(tokens) == 2) {
319
+ const gchar * name;
320
+ VALUE value;
321
+
322
+ name = tokens[0];
323
+ value = rbGObject_marshal_string(tokens[1]);
324
+
325
+ rb_hash_aset(result, ID2SYM(rb_intern(name)), value);
326
+ }
327
+
328
+ g_strfreev(tokens);
329
+ }
330
+
331
+ return result;
332
+ }
333
+
334
+ VALUE rbGObject_marshal_bytes(GBytes * bytes)
335
+ {
336
+ if (!bytes) return (Qnil);
337
+ gconstpointer data;
338
+ gsize size;
339
+
340
+ data = g_bytes_get_data (bytes, &size);
341
+ return (rb_str_new((const char *)data, size));
342
+ }
343
+
344
+ static VALUE rbGObject_marshal_object(gpointer handle, GType type)
345
+ {
346
+ VALUE object = Qnil;
347
+
348
+ if (!handle)
349
+ return (Qnil);
350
+ g_object_ref(handle);
351
+ if (type == FRIDA_TYPE_DEVICE_MANAGER)
352
+ object = DeviceManager_from_FridaDeviceManager(handle);
353
+ else if (type == FRIDA_TYPE_DEVICE)
354
+ object = Device_from_FridaDevice(handle);
355
+ else if (type == FRIDA_TYPE_APPLICATION)
356
+ object = Application_from_FridaApplication(handle);
357
+ else if (type == FRIDA_TYPE_PROCESS)
358
+ object = Process_from_FridaProcess(handle);
359
+ else if (type == FRIDA_TYPE_SPAWN)
360
+ object = Spawn_from_FridaSpawn(handle);
361
+ else if (type == FRIDA_TYPE_CHILD)
362
+ object = Child_from_FridaChild(handle);
363
+ else if (type == FRIDA_TYPE_BUS)
364
+ object = Bus_from_FridaBus(handle);
365
+ else if (type == FRIDA_TYPE_SESSION)
366
+ object = Session_from_FridaSession(handle);
367
+ else if (type == FRIDA_TYPE_SCRIPT)
368
+ object = Script_from_FridaScript(handle);
369
+ else if (type == FRIDA_TYPE_RELAY)
370
+ object = Relay_from_FridaRelay(handle);
371
+ else if (type == FRIDA_TYPE_PORTAL_MEMBERSHIP)
372
+ object = PortalMembership_from_FridaPortalMembership(handle);
373
+ else if (type == G_TYPE_IO_STREAM)
374
+ object = IOStream_from_GIOStream(handle);
375
+ else if (type == FRIDA_TYPE_CRASH)
376
+ object = Crash_from_FridaCrash(handle);
377
+ else if (type == FRIDA_TYPE_FILE_MONITOR)
378
+ object = FileMonitor_from_FridaFileMonitor(handle);
379
+ else if (type == FRIDA_TYPE_COMPILER)
380
+ object = Compiler_from_FridaCompiler(handle);
381
+ return (object);
382
+ }
383
+
384
+ static VALUE rbGObject_marshal_socket_address(GSocketAddress * address)
385
+ {
386
+ VALUE result = Qnil;
387
+
388
+ if (G_IS_INET_SOCKET_ADDRESS (address)) {
389
+ GInetSocketAddress * sa;
390
+ GInetAddress * ia;
391
+ gchar * host;
392
+ guint16 port;
393
+
394
+ sa = G_INET_SOCKET_ADDRESS (address);
395
+ ia = g_inet_socket_address_get_address (sa);
396
+
397
+ host = g_inet_address_to_string (ia);
398
+ port = g_inet_socket_address_get_port (sa);
399
+
400
+ if (g_socket_address_get_family (address) == G_SOCKET_FAMILY_IPV4)
401
+ result = rb_sprintf("(%s, %d)", host, port);
402
+ else
403
+ result = rb_sprintf("(%s, %d, %d, %d)", host, port, g_inet_socket_address_get_flowinfo(sa), g_inet_socket_address_get_scope_id(sa));
404
+
405
+ g_free (host);
406
+ } else if (G_IS_UNIX_SOCKET_ADDRESS (address)) {
407
+ GUnixSocketAddress * sa = G_UNIX_SOCKET_ADDRESS (address);
408
+
409
+ switch (g_unix_socket_address_get_address_type (sa)) {
410
+ case G_UNIX_SOCKET_ADDRESS_ANONYMOUS: {
411
+ result = rb_str_new_cstr ("");
412
+ break;
413
+ }
414
+ case G_UNIX_SOCKET_ADDRESS_PATH: {
415
+ gchar * path = g_filename_to_utf8 (g_unix_socket_address_get_path (sa), -1, NULL, NULL, NULL);
416
+ result = rb_str_new_cstr (path);
417
+ g_free (path);
418
+ break;
419
+ }
420
+ case G_UNIX_SOCKET_ADDRESS_ABSTRACT:
421
+ case G_UNIX_SOCKET_ADDRESS_ABSTRACT_PADDED: {
422
+ result = rb_str_new (g_unix_socket_address_get_path (sa), g_unix_socket_address_get_path_len (sa));
423
+ break;
424
+ }
425
+ default: {
426
+ result = Qnil;
427
+ break;
428
+ }
429
+ }
430
+ }
431
+ return result;
432
+ }
433
+
434
+ VALUE rbGObject_marshal_value(const GValue *value)
435
+ {
436
+ GType type;
437
+
438
+ type = G_VALUE_TYPE(value);
439
+ switch (type) {
440
+ case G_TYPE_BOOLEAN:
441
+ return (g_value_get_boolean(value) ? Qtrue : Qfalse);
442
+
443
+ case G_TYPE_INT:
444
+ return LL2NUM(g_value_get_int(value));
445
+
446
+ case G_TYPE_UINT:
447
+ return UINT2NUM(g_value_get_uint(value));
448
+
449
+ case G_TYPE_FLOAT:
450
+ return DBL2NUM(g_value_get_float(value));
451
+
452
+ case G_TYPE_DOUBLE:
453
+ return DBL2NUM(g_value_get_double(value));
454
+
455
+ case G_TYPE_STRING:
456
+ return rbGObject_marshal_string(g_value_get_string(value));
457
+
458
+ case G_TYPE_VARIANT:
459
+ return rbGObject_marshal_variant(g_value_get_variant(value));
460
+
461
+ default:
462
+ if (G_TYPE_IS_ENUM(type))
463
+ return rbGObject_marshal_enum(g_value_get_enum(value), type);
464
+
465
+ if (type == G_TYPE_BYTES) {
466
+ return rbGObject_marshal_bytes(g_value_get_boxed(value));
467
+ }
468
+
469
+ if (G_TYPE_IS_OBJECT(type)) {
470
+ if (G_IS_SOCKET_ADDRESS(g_value_get_object(value)))
471
+ return (rbGObject_marshal_socket_address(g_value_get_object(value)));
472
+ return rbGObject_marshal_object(g_value_get_object(value), type);
473
+ }
474
+ goto unsupported_type;
475
+ }
476
+
477
+ g_assert_not_reached();
478
+
479
+ unsupported_type: {
480
+ raise_rerror("unsupported type", NULL);
481
+ return (Qnil);
482
+ }
483
+ }
484
+
485
+ VALUE *rbGObjectSignalClosure_marshal_params(const GValue *params, guint params_length)
486
+ {
487
+ VALUE *args;
488
+
489
+ args = malloc(sizeof(VALUE) * params_length);
490
+
491
+ for (uint i = 0; i < params_length; i++) {
492
+ VALUE arg;
493
+
494
+ arg = rbGObject_marshal_value(&params[i]);
495
+ args[i] = arg;
496
+ }
497
+ return args;
498
+ }