2 * Copyright (C) 2016 "IoT.bzh"
3 * Author: José Bollo <jose.bollo@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
23 #include <json-c/json.h>
24 #include <afb/afb-req-itf.h>
26 #include "afb-subcall.h"
27 #include "afb-msg-json.h"
29 #include "afb-context.h"
34 static void subcall_addref(struct afb_subcall *subcall);
35 static void subcall_unref(struct afb_subcall *subcall);
36 static struct json_object *subcall_json(struct afb_subcall *subcall);
37 static struct afb_arg subcall_get(struct afb_subcall *subcall, const char *name);
38 static void subcall_fail(struct afb_subcall *subcall, const char *status, const char *info);
39 static void subcall_success(struct afb_subcall *subcall, struct json_object *obj, const char *info);
40 static const char *subcall_raw(struct afb_subcall *subcall, size_t *size);
41 static void subcall_send(struct afb_subcall *subcall, const char *buffer, size_t size);
42 static int subcall_subscribe(struct afb_subcall *subcall, struct afb_event event);
43 static int subcall_unsubscribe(struct afb_subcall *subcall, struct afb_event event);
44 static void subcall_session_close(struct afb_subcall *subcall);
45 static int subcall_session_set_LOA(struct afb_subcall *subcall, unsigned loa);
46 static void subcall_subcall(struct afb_subcall *subcall, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure);
48 const struct afb_req_itf afb_subcall_req_itf = {
49 .json = (void*)subcall_json,
50 .get = (void*)subcall_get,
51 .success = (void*)subcall_success,
52 .fail = (void*)subcall_fail,
53 .raw = (void*)subcall_raw,
54 .send = (void*)subcall_send,
55 .context_get = (void*)afb_context_get,
56 .context_set = (void*)afb_context_set,
57 .addref = (void*)subcall_addref,
58 .unref = (void*)subcall_unref,
59 .session_close = (void*)subcall_session_close,
60 .session_set_LOA = (void*)subcall_session_set_LOA,
61 .subscribe = (void*)subcall_subscribe,
62 .unsubscribe = (void*)subcall_unsubscribe,
63 .subcall = (void*)subcall_subcall
69 * CAUTION: 'context' field should be the first because there
70 * is an implicit convertion to struct afb_context
72 struct afb_context context;
73 struct afb_context *original_context;
75 struct json_object *args;
77 void (*callback)(void*, int, struct json_object*);
81 static void subcall_addref(struct afb_subcall *subcall)
86 static void subcall_unref(struct afb_subcall *subcall)
88 if (0 == --subcall->refcount) {
89 json_object_put(subcall->args);
90 afb_req_unref(subcall->req);
95 static struct json_object *subcall_json(struct afb_subcall *subcall)
100 static struct afb_arg subcall_get(struct afb_subcall *subcall, const char *name)
103 struct json_object *value;
105 if (json_object_object_get_ex(subcall->args, name, &value)) {
107 arg.value = json_object_get_string(value);
116 static void subcall_emit(struct afb_subcall *subcall, int iserror, struct json_object *object)
118 if (subcall->context.refreshing != 0)
119 subcall->original_context->refreshing = 1;
121 subcall->callback(subcall->closure, iserror, object);
122 json_object_put(object);
125 static void subcall_fail(struct afb_subcall *subcall, const char *status, const char *info)
127 subcall_emit(subcall, 1, afb_msg_json_reply_error(status, info, NULL, NULL));
130 static void subcall_success(struct afb_subcall *subcall, struct json_object *obj, const char *info)
132 subcall_emit(subcall, 0, afb_msg_json_reply_ok(info, obj, NULL, NULL));
135 static const char *subcall_raw(struct afb_subcall *subcall, size_t *size)
137 const char *result = json_object_to_json_string(subcall->args);
139 *size = strlen(result);
143 static void subcall_send(struct afb_subcall *subcall, const char *buffer, size_t size)
145 subcall_emit(subcall, 0, json_tokener_parse(buffer));
148 static void subcall_session_close(struct afb_subcall *subcall)
150 afb_req_session_close(subcall->req);
153 static int subcall_session_set_LOA(struct afb_subcall *subcall, unsigned loa)
155 return afb_req_session_set_LOA(subcall->req, loa);
158 static int subcall_subscribe(struct afb_subcall *subcall, struct afb_event event)
160 return afb_req_subscribe(subcall->req, event);
163 static int subcall_unsubscribe(struct afb_subcall *subcall, struct afb_event event)
165 return afb_req_unsubscribe(subcall->req, event);
168 static void subcall_subcall(struct afb_subcall *subcall, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure)
170 afb_subcall(&subcall->context, api, verb, args, callback, closure, (struct afb_req){ .itf = &afb_subcall_req_itf, .closure = subcall });
173 void afb_subcall(struct afb_context *context, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure, struct afb_req req)
175 struct afb_subcall *subcall;
177 subcall = calloc(1, sizeof *subcall);
178 if (subcall == NULL) {
179 callback(closure, 1, afb_msg_json_reply_error("failed", "out of memory", NULL, NULL));
183 subcall->original_context = context;
184 subcall->refcount = 1;
185 subcall->args = args;
187 subcall->callback = callback;
188 subcall->closure = closure;
189 subcall->context = *context;
191 afb_apis_call_((struct afb_req){ .itf = &afb_subcall_req_itf, .closure = subcall }, &subcall->context, api, verb);
192 subcall_unref(subcall);