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)
102 return afb_msg_json_get_arg(subcall->args, name);
105 static void subcall_emit(struct afb_subcall *subcall, int iserror, struct json_object *object)
107 if (subcall->context.refreshing != 0)
108 subcall->original_context->refreshing = 1;
110 subcall->callback(subcall->closure, iserror, object);
111 json_object_put(object);
114 static void subcall_fail(struct afb_subcall *subcall, const char *status, const char *info)
116 subcall_emit(subcall, 1, afb_msg_json_reply_error(status, info, NULL, NULL));
119 static void subcall_success(struct afb_subcall *subcall, struct json_object *obj, const char *info)
121 subcall_emit(subcall, 0, afb_msg_json_reply_ok(info, obj, NULL, NULL));
124 static const char *subcall_raw(struct afb_subcall *subcall, size_t *size)
126 const char *result = json_object_to_json_string(subcall->args);
128 *size = strlen(result);
132 static void subcall_send(struct afb_subcall *subcall, const char *buffer, size_t size)
134 subcall_emit(subcall, 0, json_tokener_parse(buffer));
137 static void subcall_session_close(struct afb_subcall *subcall)
139 afb_req_session_close(subcall->req);
142 static int subcall_session_set_LOA(struct afb_subcall *subcall, unsigned loa)
144 return afb_req_session_set_LOA(subcall->req, loa);
147 static int subcall_subscribe(struct afb_subcall *subcall, struct afb_event event)
149 return afb_req_subscribe(subcall->req, event);
152 static int subcall_unsubscribe(struct afb_subcall *subcall, struct afb_event event)
154 return afb_req_unsubscribe(subcall->req, event);
157 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)
159 afb_subcall(&subcall->context, api, verb, args, callback, closure, (struct afb_req){ .itf = &afb_subcall_req_itf, .closure = subcall });
162 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)
164 struct afb_subcall *subcall;
166 subcall = calloc(1, sizeof *subcall);
167 if (subcall == NULL) {
168 callback(closure, 1, afb_msg_json_reply_error("failed", "out of memory", NULL, NULL));
172 subcall->original_context = context;
173 subcall->refcount = 1;
174 subcall->args = args;
176 subcall->callback = callback;
177 subcall->closure = closure;
178 subcall->context = *context;
180 afb_apis_call_((struct afb_req){ .itf = &afb_subcall_req_itf, .closure = subcall }, &subcall->context, api, verb);
181 subcall_unref(subcall);