~azzar1/snapd-glib-fork/glib-2-40

« back to all changes in this revision

Viewing changes to snapd-glib/snapd-client.c

  • Committer: Robert Ancell
  • Date: 2016-08-30 04:23:53 UTC
  • Revision ID: git-v1:286dc90ad146fa4df2ba64e0382eaf91340ef721
Make a D-Bus service to allow non-root users to login

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
 
33
33
G_DEFINE_TYPE_WITH_PRIVATE (SnapdClient, snapd_client, G_TYPE_OBJECT)
34
34
 
35
 
G_DEFINE_QUARK (snapd-client-error-quark, snapd_client_error)
 
35
G_DEFINE_QUARK (snapd-error-quark, snapd_error)
36
36
 
37
37
/* snapd API documentation is at https://github.com/snapcore/snapd/blob/master/docs/rest.md */
38
38
 
45
45
 
46
46
// FIXME: Make multiple async requests work at the same time
47
47
 
 
48
G_DECLARE_FINAL_TYPE (SnapdLoginRequest, snapd_login_request, SNAPD, LOGIN_REQUEST, GObject)
 
49
 
 
50
struct _SnapdLoginRequest
 
51
{
 
52
    GObject parent_instance;
 
53
 
 
54
    GCancellable *cancellable;
 
55
    GAsyncReadyCallback ready_callback;
 
56
    gpointer ready_callback_data;
 
57
 
 
58
    gchar *username;
 
59
    gchar *password;
 
60
    gchar *otp;
 
61
    SnapdAuthData *auth_data;
 
62
    GError *error;
 
63
};
 
64
 
48
65
typedef enum
49
66
{
50
67
    SNAPD_REQUEST_GET_SYSTEM_INFORMATION,
105
122
    GPtrArray *methods;
106
123
};
107
124
 
 
125
static void
 
126
snapd_login_request_async_result_init (GAsyncResultIface *iface)
 
127
{
 
128
}
 
129
 
 
130
G_DEFINE_TYPE_WITH_CODE (SnapdLoginRequest, snapd_login_request, G_TYPE_OBJECT,
 
131
                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, snapd_login_request_async_result_init))
 
132
 
 
133
static void
 
134
snapd_login_request_finalize (GObject *object)
 
135
{
 
136
    SnapdLoginRequest *request = SNAPD_LOGIN_REQUEST (object);
 
137
 
 
138
    g_clear_object (&request->cancellable);
 
139
    g_free (request->username);
 
140
    g_free (request->password);
 
141
    g_free (request->otp);
 
142
    g_clear_object (&request->auth_data);
 
143
    g_clear_object (&request->error);
 
144
}
 
145
 
 
146
static void
 
147
snapd_login_request_class_init (SnapdLoginRequestClass *klass)
 
148
{
 
149
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
150
 
 
151
   gobject_class->finalize = snapd_login_request_finalize;
 
152
}
 
153
 
 
154
static void
 
155
snapd_login_request_init (SnapdLoginRequest *request)
 
156
{
 
157
}
 
158
 
 
159
/**
 
160
 * snapd_login_sync:
 
161
 * @username: usename to log in with.
 
162
 * @password: password to log in with.
 
163
 * @otp: (allow-none): response to one-time password challenge.
 
164
 * @cancellable: (allow-none): a #GCancellable or %NULL.
 
165
 * @error: (allow-none): #GError location to store the error occurring, or %NULL to ignore.
 
166
 *
 
167
 * Returns: (transfer full): a #SnapdAuthData or %NULL on error.
 
168
 */
 
169
SnapdAuthData *
 
170
snapd_login_sync (const gchar *username, const gchar *password, const gchar *otp,
 
171
                  GCancellable *cancellable, GError **error)
 
172
{
 
173
    g_autoptr(GDBusConnection) c = NULL;
 
174
    g_autoptr(GVariant) result = NULL;
 
175
    const gchar *macaroon;
 
176
    gchar **discharges;
 
177
 
 
178
    g_return_val_if_fail (username != NULL, NULL);
 
179
    g_return_val_if_fail (password != NULL, NULL);
 
180
 
 
181
    if (otp == NULL)
 
182
        otp = "";
 
183
 
 
184
    c = g_bus_get_sync (G_BUS_TYPE_SYSTEM, cancellable, error);
 
185
    if (c == NULL)
 
186
        return NULL;
 
187
    result = g_dbus_connection_call_sync (c,
 
188
                                          "io.snapcraft.SnapdLoginService",
 
189
                                          "/io/snapcraft/SnapdLoginService",
 
190
                                          "io.snapcraft.SnapdLoginService",
 
191
                                          "Login",
 
192
                                          g_variant_new ("(sss)", username, password, otp),
 
193
                                          G_VARIANT_TYPE ("(sas)"),
 
194
                                          G_DBUS_CALL_FLAGS_NONE,
 
195
                                          -1,
 
196
                                          cancellable,
 
197
                                          error);
 
198
    if (result == NULL)
 
199
        return NULL;
 
200
 
 
201
    g_variant_get (result, "(&s&as)", &macaroon, &discharges);
 
202
 
 
203
    return snapd_auth_data_new (macaroon, discharges);
 
204
}
 
205
 
 
206
static gboolean
 
207
login_complete_cb (gpointer user_data)
 
208
{
 
209
    g_autoptr(SnapdLoginRequest) request = user_data;
 
210
 
 
211
    if (request->ready_callback != NULL)
 
212
        request->ready_callback (NULL, G_ASYNC_RESULT (request), request->ready_callback_data);
 
213
 
 
214
    return G_SOURCE_REMOVE;
 
215
}
 
216
 
 
217
static void
 
218
login_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 
219
{
 
220
    g_autoptr(SnapdLoginRequest) request = user_data;
 
221
    g_autoptr(GVariant) r = NULL;
 
222
    const gchar *macaroon;
 
223
    gchar **discharges;
 
224
    g_autoptr(GError) error = NULL;
 
225
 
 
226
    r = g_dbus_connection_call_finish (G_DBUS_CONNECTION (object), result, &error);
 
227
    if (r == NULL) {
 
228
        request->error = g_error_new (SNAPD_ERROR,
 
229
                                      SNAPD_ERROR_CONNECTION_FAILED,
 
230
                                      "Failed to get call login: %s", error->message);
 
231
        return;
 
232
    }
 
233
 
 
234
    g_variant_get (r, "(&s&as)", &macaroon, &discharges);
 
235
    request->auth_data = snapd_auth_data_new (macaroon, discharges);
 
236
 
 
237
    g_idle_add (login_complete_cb, g_steal_pointer (&request));
 
238
}
 
239
 
 
240
static void
 
241
bus_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 
242
{
 
243
    g_autoptr(SnapdLoginRequest) request = user_data;
 
244
    g_autoptr(GDBusConnection) c = NULL;
 
245
    g_autoptr(GError) error = NULL;
 
246
 
 
247
    c = g_bus_get_finish (result, &error);
 
248
    if (c == NULL) {
 
249
        request->error = g_error_new (SNAPD_ERROR,
 
250
                                      SNAPD_ERROR_CONNECTION_FAILED,
 
251
                                      "Failed to get system bus: %s", error->message);
 
252
        g_idle_add (login_complete_cb, g_steal_pointer (&request));
 
253
        return;
 
254
    }
 
255
 
 
256
    g_dbus_connection_call (c,
 
257
                            "io.snapcraft.SnapdLoginService",
 
258
                            "/io/snapcraft/SnapdLoginService",
 
259
                            "io.snapcraft.SnapdLoginService",
 
260
                            "Login",
 
261
                            g_variant_new ("(sss)", request->username, request->password, request->otp),
 
262
                            G_VARIANT_TYPE ("(sas)"),
 
263
                            G_DBUS_CALL_FLAGS_NONE,
 
264
                            -1,
 
265
                            request->cancellable,
 
266
                            login_cb,
 
267
                            request);
 
268
    g_steal_pointer (&request);
 
269
}
 
270
 
 
271
/**
 
272
 * snapd_login_async:
 
273
 * @username: usename to log in with.
 
274
 * @password: password to log in with.
 
275
 * @otp: (allow-none): response to one-time password challenge.
 
276
 * @cancellable: (allow-none): a #GCancellable or %NULL.
 
277
 * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied.
 
278
 * @user_data: (closure): the data to pass to callback function.
 
279
 */
 
280
void
 
281
snapd_login_async (const gchar *username, const gchar *password, const gchar *otp,
 
282
                   GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
 
283
{
 
284
    SnapdLoginRequest *request;
 
285
 
 
286
    g_return_if_fail (username != NULL);
 
287
    g_return_if_fail (password != NULL);
 
288
 
 
289
    request = g_object_new (snapd_login_request_get_type (), NULL);
 
290
    request->ready_callback = callback;
 
291
    request->ready_callback_data = user_data;
 
292
    request->cancellable = g_object_ref (cancellable);
 
293
    request->username = g_strdup (username);
 
294
    request->password = g_strdup (password);
 
295
    request->otp = otp != NULL ? g_strdup (otp) : "";
 
296
 
 
297
    g_bus_get (G_BUS_TYPE_SYSTEM, cancellable, bus_cb, NULL);
 
298
}
 
299
 
 
300
/**
 
301
 * snapd_login_finish:
 
302
 * @result: a #GAsyncResult.
 
303
 * @error: (allow-none): #GError location to store the error occurring, or %NULL to ignore.
 
304
 *
 
305
 * Returns: (transfer full): a #SnapdAuthData or %NULL on error.
 
306
 */
 
307
SnapdAuthData *
 
308
snapd_login_finish (GAsyncResult *result, GError **error)
 
309
{
 
310
    SnapdLoginRequest *request = SNAPD_LOGIN_REQUEST (result);
 
311
 
 
312
    if (request->error)
 
313
        g_propagate_error (error, request->error);
 
314
 
 
315
    return g_steal_pointer (&request->auth_data);
 
316
}
 
317
 
108
318
static gboolean
109
319
complete_cb (gpointer user_data)
110
320
{
111
 
    SnapdRequest *request = user_data;
 
321
    g_autoptr(SnapdRequest) request = user_data;
112
322
    SnapdClientPrivate *priv = snapd_client_get_instance_private (request->client);
113
 
  
 
323
 
 
324
    priv->requests = g_list_remove (priv->requests, request);
 
325
 
114
326
    if (request->ready_callback != NULL)
115
327
        request->ready_callback (G_OBJECT (request->client), G_ASYNC_RESULT (request), request->ready_callback_data);
116
328
 
117
 
    priv->requests = g_list_remove (priv->requests, request);
118
 
    g_object_unref (request);
119
 
 
120
329
    return G_SOURCE_REMOVE;
121
330
}
122
331
 
191
400
    g_clear_object (&request->received_auth_data);
192
401
    g_clear_pointer (&request->plugs, g_ptr_array_unref);
193
402
    g_clear_pointer (&request->slots, g_ptr_array_unref);
194
 
    g_clear_pointer (&request->methods, g_ptr_array_unref);  
 
403
    g_clear_pointer (&request->methods, g_ptr_array_unref);
195
404
}
196
405
 
197
406
static void
267
476
    // FIXME: Check for short writes
268
477
    n_written = g_socket_send (priv->snapd_socket, request_data->str, request_data->len, request->cancellable, &local_error);
269
478
    if (n_written < 0) {
270
 
        GError *error = g_error_new (SNAPD_CLIENT_ERROR,
271
 
                                     SNAPD_CLIENT_ERROR_WRITE_ERROR,
 
479
        GError *error = g_error_new (SNAPD_ERROR,
 
480
                                     SNAPD_ERROR_WRITE_ERROR,
272
481
                                     "Failed to write to snapd: %s",
273
482
                                     local_error->message);
274
483
        snapd_request_complete (request, error);
342
551
 
343
552
        return TRUE;
344
553
    }
345
 
    /* Example: 20160517 */  
 
554
    /* Example: 20160517 */
346
555
    else if (strlen (date_string) == 8) {
347
556
        // FIXME: Implement
348
557
        return FALSE;
416
625
        if (!parse_time (tokens[1], &hour, &minute, &seconds))
417
626
            return NULL;
418
627
    }
419
 
  
 
628
 
420
629
    if (timezone == NULL)
421
630
        timezone = g_time_zone_new_local ();
422
631
 
433
642
 
434
643
    if (content_type == NULL) {
435
644
        g_set_error_literal (error,
436
 
                             SNAPD_CLIENT_ERROR,
437
 
                             SNAPD_CLIENT_ERROR_PARSE_ERROR,
 
645
                             SNAPD_ERROR,
 
646
                             SNAPD_ERROR_PARSE_ERROR,
438
647
                             "snapd returned no content type");
439
648
        return FALSE;
440
649
    }
441
650
    if (g_strcmp0 (content_type, "application/json") != 0) {
442
651
        g_set_error (error,
443
 
                     SNAPD_CLIENT_ERROR,
444
 
                     SNAPD_CLIENT_ERROR_PARSE_ERROR,
 
652
                     SNAPD_ERROR,
 
653
                     SNAPD_ERROR_PARSE_ERROR,
445
654
                     "snapd returned unexpected content type %s", content_type);
446
655
        return FALSE;
447
656
    }
449
658
    parser = json_parser_new ();
450
659
    if (!json_parser_load_from_data (parser, content, content_length, &error_local)) {
451
660
        g_set_error (error,
452
 
                     SNAPD_CLIENT_ERROR,
453
 
                     SNAPD_CLIENT_ERROR_PARSE_ERROR,
 
661
                     SNAPD_ERROR,
 
662
                     SNAPD_ERROR_PARSE_ERROR,
454
663
                     "Unable to parse snapd response: %s",
455
664
                     error_local->message);
456
665
        return FALSE;
458
667
 
459
668
    if (!JSON_NODE_HOLDS_OBJECT (json_parser_get_root (parser))) {
460
669
        g_set_error_literal (error,
461
 
                             SNAPD_CLIENT_ERROR,
462
 
                             SNAPD_CLIENT_ERROR_PARSE_ERROR,
 
670
                             SNAPD_ERROR,
 
671
                             SNAPD_ERROR_PARSE_ERROR,
463
672
                             "snapd response does is not a valid JSON object");
464
673
        return FALSE;
465
674
    }
478
687
 
479
688
        if (g_strcmp0 (kind, "login-required") == 0) {
480
689
            g_set_error_literal (error,
481
 
                                 SNAPD_CLIENT_ERROR,
482
 
                                 SNAPD_CLIENT_ERROR_LOGIN_REQUIRED,
 
690
                                 SNAPD_ERROR,
 
691
                                 SNAPD_ERROR_LOGIN_REQUIRED,
483
692
                                 message);
484
693
            return FALSE;
485
694
        }
486
695
        else if (g_strcmp0 (kind, "invalid-auth-data") == 0) {
487
696
            g_set_error_literal (error,
488
 
                                 SNAPD_CLIENT_ERROR,
489
 
                                 SNAPD_CLIENT_ERROR_INVALID_AUTH_DATA,
 
697
                                 SNAPD_ERROR,
 
698
                                 SNAPD_ERROR_INVALID_AUTH_DATA,
490
699
                                 message);
491
700
            return FALSE;
492
701
        }
493
702
        else if (g_strcmp0 (kind, "two-factor-required") == 0) {
494
703
            g_set_error_literal (error,
495
 
                                 SNAPD_CLIENT_ERROR,
496
 
                                 SNAPD_CLIENT_ERROR_TWO_FACTOR_REQUIRED,
 
704
                                 SNAPD_ERROR,
 
705
                                 SNAPD_ERROR_TWO_FACTOR_REQUIRED,
497
706
                                 message);
498
707
            return FALSE;
499
708
        }
500
709
        else if (g_strcmp0 (kind, "two-factor-failed") == 0) {
501
710
            g_set_error_literal (error,
502
 
                                 SNAPD_CLIENT_ERROR,
503
 
                                 SNAPD_CLIENT_ERROR_TWO_FACTOR_FAILED,
 
711
                                 SNAPD_ERROR,
 
712
                                 SNAPD_ERROR_TWO_FACTOR_FAILED,
504
713
                                 message);
505
714
            return FALSE;
506
715
        }
507
716
        else if (status_code == SOUP_STATUS_BAD_REQUEST) {
508
717
            g_set_error_literal (error,
509
 
                                 SNAPD_CLIENT_ERROR,
510
 
                                 SNAPD_CLIENT_ERROR_BAD_REQUEST,
 
718
                                 SNAPD_ERROR,
 
719
                                 SNAPD_ERROR_BAD_REQUEST,
511
720
                                 message);
512
721
            return FALSE;
513
722
        }
514
723
        else {
515
724
            g_set_error_literal (error,
516
 
                                 SNAPD_CLIENT_ERROR,
517
 
                                 SNAPD_CLIENT_ERROR_GENERAL_ERROR,
 
725
                                 SNAPD_ERROR,
 
726
                                 SNAPD_ERROR_GENERAL_ERROR,
518
727
                                 message);
519
728
            return FALSE;
520
729
        }
548
757
 
549
758
    result = get_object (response, "result");
550
759
    if (result == NULL) {
551
 
        error = g_error_new (SNAPD_CLIENT_ERROR,
552
 
                             SNAPD_CLIENT_ERROR_READ_ERROR,
 
760
        error = g_error_new (SNAPD_ERROR,
 
761
                             SNAPD_ERROR_READ_ERROR,
553
762
                             "No result returned");
554
763
        snapd_request_complete (request, error);
555
764
        return;
618
827
 
619
828
        if (json_node_get_value_type (node) != JSON_TYPE_OBJECT) {
620
829
            g_set_error_literal (error,
621
 
                                 SNAPD_CLIENT_ERROR,
622
 
                                 SNAPD_CLIENT_ERROR_READ_ERROR,
 
830
                                 SNAPD_ERROR,
 
831
                                 SNAPD_ERROR_READ_ERROR,
623
832
                                 "Unexpected app type");
624
833
            return NULL;
625
834
        }
642
851
 
643
852
        if (json_node_get_value_type (node) != JSON_TYPE_OBJECT) {
644
853
            g_set_error_literal (error,
645
 
                                 SNAPD_CLIENT_ERROR,
646
 
                                 SNAPD_CLIENT_ERROR_READ_ERROR,
 
854
                                 SNAPD_ERROR,
 
855
                                 SNAPD_ERROR_READ_ERROR,
647
856
                                 "Unexpected price type");
648
857
            return NULL;
649
858
        }
693
902
 
694
903
        if (json_node_get_value_type (node) != JSON_TYPE_OBJECT) {
695
904
            g_set_error_literal (error,
696
 
                                 SNAPD_CLIENT_ERROR,
697
 
                                 SNAPD_CLIENT_ERROR_READ_ERROR,
 
905
                                 SNAPD_ERROR,
 
906
                                 SNAPD_ERROR_READ_ERROR,
698
907
                                 "Unexpected snap type");
699
908
            return NULL;
700
909
        }
726
935
    }
727
936
 
728
937
    if (code != SOUP_STATUS_OK) {
729
 
        GError *error = g_error_new (SNAPD_CLIENT_ERROR,
730
 
                                     SNAPD_CLIENT_ERROR_READ_ERROR,
 
938
        GError *error = g_error_new (SNAPD_ERROR,
 
939
                                     SNAPD_ERROR_READ_ERROR,
731
940
                                     "Got response %u retrieving icon", code);
732
941
        snapd_request_complete (request, error);
733
942
    }
781
990
 
782
991
    result = get_object (response, "result");
783
992
    if (result == NULL) {
784
 
        error = g_error_new (SNAPD_CLIENT_ERROR,
785
 
                             SNAPD_CLIENT_ERROR_READ_ERROR,
 
993
        error = g_error_new (SNAPD_ERROR,
 
994
                             SNAPD_ERROR_READ_ERROR,
786
995
                             "No result returned");
787
996
        snapd_request_complete (request, error);
788
997
        return;
814
1023
 
815
1024
        if (json_node_get_value_type (node) != JSON_TYPE_OBJECT) {
816
1025
            g_set_error_literal (error,
817
 
                                 SNAPD_CLIENT_ERROR,
818
 
                                 SNAPD_CLIENT_ERROR_READ_ERROR,
 
1026
                                 SNAPD_ERROR,
 
1027
                                 SNAPD_ERROR_READ_ERROR,
819
1028
                                 "Unexpected connection type");
820
1029
            return NULL;
821
1030
        }
850
1059
 
851
1060
    result = get_object (response, "result");
852
1061
    if (result == NULL) {
853
 
        error = g_error_new (SNAPD_CLIENT_ERROR,
854
 
                             SNAPD_CLIENT_ERROR_READ_ERROR,
 
1062
        error = g_error_new (SNAPD_ERROR,
 
1063
                             SNAPD_ERROR_READ_ERROR,
855
1064
                             "No result returned");
856
1065
        snapd_request_complete (request, error);
857
1066
        return;
866
1075
        g_autoptr(SnapdPlug) plug = NULL;
867
1076
 
868
1077
        if (json_node_get_value_type (node) != JSON_TYPE_OBJECT) {
869
 
            error = g_error_new (SNAPD_CLIENT_ERROR,
870
 
                                 SNAPD_CLIENT_ERROR_READ_ERROR,
 
1078
            error = g_error_new (SNAPD_ERROR,
 
1079
                                 SNAPD_ERROR_READ_ERROR,
871
1080
                                 "Unexpected plug type");
872
1081
            snapd_request_complete (request, error);
873
1082
            return;
900
1109
        g_autoptr(SnapdSlot) slot = NULL;
901
1110
 
902
1111
        if (json_node_get_value_type (node) != JSON_TYPE_OBJECT) {
903
 
            error = g_error_new (SNAPD_CLIENT_ERROR,
904
 
                                 SNAPD_CLIENT_ERROR_READ_ERROR,
 
1112
            error = g_error_new (SNAPD_ERROR,
 
1113
                                 SNAPD_ERROR_READ_ERROR,
905
1114
                                 "Unexpected slot type");
906
1115
            snapd_request_complete (request, error);
907
1116
            return;
953
1162
 
954
1163
    request->timeout_timer = 0;
955
1164
 
956
 
    error = g_error_new (SNAPD_CLIENT_ERROR,
957
 
                         SNAPD_CLIENT_ERROR_READ_ERROR,
 
1165
    error = g_error_new (SNAPD_ERROR,
 
1166
                         SNAPD_ERROR_READ_ERROR,
958
1167
                         "Timeout waiting for snapd");
959
1168
    snapd_request_complete (request, error);
960
1169
 
978
1187
           g_strcmp0 (snapd_task_get_status (task1), snapd_task_get_status (task2)) == 0 &&
979
1188
           !!snapd_task_get_ready (task1) == !!snapd_task_get_ready (task2) &&
980
1189
           snapd_task_get_progress_done (task1) == snapd_task_get_progress_done (task2) &&
981
 
           snapd_task_get_progress_total (task1) == snapd_task_get_progress_total (task2) &&    
 
1190
           snapd_task_get_progress_total (task1) == snapd_task_get_progress_total (task2) &&
982
1191
           times_equal (snapd_task_get_spawn_time (task1), snapd_task_get_spawn_time (task2)) &&
983
1192
           times_equal (snapd_task_get_spawn_time (task1), snapd_task_get_spawn_time (task2));
984
1193
}
1034
1243
    /* First run we expect the change ID, following runs are updates */
1035
1244
    if (request->change_id == NULL) {
1036
1245
         if (change_id == NULL) {
1037
 
             g_error_new (SNAPD_CLIENT_ERROR,
1038
 
                          SNAPD_CLIENT_ERROR_READ_ERROR,
 
1246
             g_error_new (SNAPD_ERROR,
 
1247
                          SNAPD_ERROR_READ_ERROR,
1039
1248
                          "No async response received");
1040
1249
             snapd_request_complete (request, error);
1041
1250
             return;
1048
1257
        JsonObject *result;
1049
1258
 
1050
1259
        if (change_id != NULL) {
1051
 
             error = g_error_new (SNAPD_CLIENT_ERROR,
1052
 
                                  SNAPD_CLIENT_ERROR_READ_ERROR,
 
1260
             error = g_error_new (SNAPD_ERROR,
 
1261
                                  SNAPD_ERROR_READ_ERROR,
1053
1262
                                  "Duplicate async response received");
1054
1263
             snapd_request_complete (request, error);
1055
1264
             return;
1057
1266
 
1058
1267
        result = get_object (response, "result");
1059
1268
        if (result == NULL) {
1060
 
            error = g_error_new (SNAPD_CLIENT_ERROR,
1061
 
                                 SNAPD_CLIENT_ERROR_READ_ERROR,
 
1269
            error = g_error_new (SNAPD_ERROR,
 
1270
                                 SNAPD_ERROR_READ_ERROR,
1062
1271
                                 "No async result returned");
1063
1272
            snapd_request_complete (request, error);
1064
1273
            return;
1065
1274
        }
1066
1275
 
1067
1276
        if (g_strcmp0 (request->change_id, get_string (result, "id", NULL)) != 0) {
1068
 
            error = g_error_new (SNAPD_CLIENT_ERROR,
1069
 
                                 SNAPD_CLIENT_ERROR_READ_ERROR,
 
1277
            error = g_error_new (SNAPD_ERROR,
 
1278
                                 SNAPD_ERROR_READ_ERROR,
1070
1279
                                 "Unexpected change ID returned");
1071
1280
            snapd_request_complete (request, error);
1072
1281
            return;
1091
1300
                g_autoptr(SnapdTask) t = NULL;
1092
1301
 
1093
1302
                if (json_node_get_value_type (node) != JSON_TYPE_OBJECT) {
1094
 
                    error = g_error_new (SNAPD_CLIENT_ERROR,
1095
 
                                         SNAPD_CLIENT_ERROR_READ_ERROR,
 
1303
                    error = g_error_new (SNAPD_ERROR,
 
1304
                                         SNAPD_ERROR_READ_ERROR,
1096
1305
                                         "Unexpected task type");
1097
1306
                    snapd_request_complete (request, error);
1098
1307
                    return;
1181
1390
 
1182
1391
    result = get_object (response, "result");
1183
1392
    if (result == NULL) {
1184
 
        error = g_error_new (SNAPD_CLIENT_ERROR,
1185
 
                             SNAPD_CLIENT_ERROR_READ_ERROR,
 
1393
        error = g_error_new (SNAPD_ERROR,
 
1394
                             SNAPD_ERROR_READ_ERROR,
1186
1395
                             "No result returned");
1187
1396
        snapd_request_complete (request, error);
1188
1397
        return;
1194
1403
        JsonNode *node = json_array_get_element (discharges, i);
1195
1404
 
1196
1405
        if (json_node_get_value_type (node) != G_TYPE_STRING) {
1197
 
            error = g_error_new (SNAPD_CLIENT_ERROR,
1198
 
                                 SNAPD_CLIENT_ERROR_READ_ERROR,
 
1406
            error = g_error_new (SNAPD_ERROR,
 
1407
                                 SNAPD_ERROR_READ_ERROR,
1199
1408
                                 "Unexpected discharge type");
1200
1409
            snapd_request_complete (request, error);
1201
1410
            return;
1252
1461
 
1253
1462
    result = get_object (response, "result");
1254
1463
    if (result == NULL) {
1255
 
        error = g_error_new (SNAPD_CLIENT_ERROR,
1256
 
                             SNAPD_CLIENT_ERROR_READ_ERROR,
 
1464
        error = g_error_new (SNAPD_ERROR,
 
1465
                             SNAPD_ERROR_READ_ERROR,
1257
1466
                             "No result returned");
1258
1467
        snapd_request_complete (request, error);
1259
1468
        return;
1271
1480
        SnapdPaymentMethod *payment_method;
1272
1481
 
1273
1482
        if (json_node_get_value_type (node) != JSON_TYPE_OBJECT) {
1274
 
            error = g_error_new (SNAPD_CLIENT_ERROR,
1275
 
                                 SNAPD_CLIENT_ERROR_READ_ERROR,
 
1483
            error = g_error_new (SNAPD_ERROR,
 
1484
                                 SNAPD_ERROR_READ_ERROR,
1276
1485
                                 "Unexpected method type");
1277
1486
            snapd_request_complete (request, error);
1278
1487
            return;
1285
1494
            JsonNode *node = json_array_get_element (currencies, j);
1286
1495
 
1287
1496
            if (json_node_get_value_type (node) != G_TYPE_STRING) {
1288
 
                error = g_error_new (SNAPD_CLIENT_ERROR,
1289
 
                                     SNAPD_CLIENT_ERROR_READ_ERROR,
 
1497
                error = g_error_new (SNAPD_ERROR,
 
1498
                                     SNAPD_ERROR_READ_ERROR,
1290
1499
                                     "Unexpected currency type");
1291
1500
                snapd_request_complete (request, error);
1292
1501
                return;
1434
1643
        parse_disable_response (request, headers, content, content_length);
1435
1644
        break;
1436
1645
    default:
1437
 
        error = g_error_new (SNAPD_CLIENT_ERROR,
1438
 
                             SNAPD_CLIENT_ERROR_GENERAL_ERROR,
 
1646
        error = g_error_new (SNAPD_ERROR,
 
1647
                             SNAPD_ERROR_GENERAL_ERROR,
1439
1648
                             "Unknown request");
1440
1649
        snapd_request_complete (request, error);
1441
1650
        break;
1463
1672
        g_printerr ("read error\n");
1464
1673
        // FIXME: Cancel all requests
1465
1674
        //g_set_error (error,
1466
 
        //             SNAPD_CLIENT_ERROR,
1467
 
        //             SNAPD_CLIENT_ERROR_READ_ERROR,
 
1675
        //             SNAPD_ERROR,
 
1676
        //             SNAPD_ERROR_READ_ERROR,
1468
1677
        //             "Failed to read from snapd: %s",
1469
1678
        //             error_local->message);
1470
1679
        return FALSE;
1657
1866
                                       &error_local);
1658
1867
    if (priv->snapd_socket == NULL) {
1659
1868
        g_set_error (error,
1660
 
                     SNAPD_CLIENT_ERROR,
1661
 
                     SNAPD_CLIENT_ERROR_CONNECTION_FAILED,
 
1869
                     SNAPD_ERROR,
 
1870
                     SNAPD_ERROR_CONNECTION_FAILED,
1662
1871
                     "Unable to open snapd socket: %s",
1663
1872
                     error_local->message);
1664
1873
        return FALSE;
1667
1876
    if (!g_socket_connect (priv->snapd_socket, address, cancellable, &error_local)) {
1668
1877
        g_clear_object (&priv->snapd_socket);
1669
1878
        g_set_error (error,
1670
 
                     SNAPD_CLIENT_ERROR,
1671
 
                     SNAPD_CLIENT_ERROR_CONNECTION_FAILED,
 
1879
                     SNAPD_ERROR,
 
1880
                     SNAPD_ERROR_CONNECTION_FAILED,
1672
1881
                     "Unable to connect snapd socket: %s",
1673
1882
                     error_local->message);
1674
1883
        g_clear_object (&priv->snapd_socket);
2018
2227
 
2019
2228
    request = SNAPD_REQUEST (result);
2020
2229
    g_return_val_if_fail (request->request_type == SNAPD_REQUEST_LIST_ONE, NULL);
2021
 
  
 
2230
 
2022
2231
    if (snapd_request_set_error (request, error))
2023
2232
        return NULL;
2024
2233
    return request->snap != NULL ? g_object_ref (request->snap) : NULL;
3331
3540
    SnapdClientPrivate *priv = snapd_client_get_instance_private (SNAPD_CLIENT (object));
3332
3541
 
3333
3542
    g_clear_object (&priv->snapd_socket);
3334
 
    g_clear_object (&priv->auth_data);  
 
3543
    g_clear_object (&priv->auth_data);
3335
3544
    g_list_free_full (priv->requests, g_object_unref);
3336
3545
    priv->requests = NULL;
3337
3546
    g_clear_pointer (&priv->read_source, g_source_unref);