Templates separation between binding API hat and Callbacks
[staging/xdg-launcher.git] / templates / service / binding / xxx-service-cb.c
1 /*
2  * Copyright (C) 2015, 2016 "IoT.bzh"
3  * Author "Fulup Ar Foll"
4  *
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
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 #define _GNU_SOURCE
19 #include <stdio.h>
20 #include <string.h>
21 #include <json-c/json.h>
22
23 #include <afb/afb-binding.h>
24  #include "xxx-service-hat.h"
25  
26  const struct afb_binding_interface *interface;
27  
28  static struct event *events = 0;
29
30 /* searchs the event of tag */
31  struct event *event_get(const char *tag)
32 {
33         struct event *e = events;
34         while(e && strcmp(e->tag, tag))
35                 e = e->next;
36         return e;
37 }
38
39 /* deletes the event of tag */
40  int event_del(const char *tag)
41 {
42         struct event *e, **p;
43
44         /* check exists */
45         e = event_get(tag);
46         if (!e) return -1;
47
48         /* unlink */
49         p = &events;
50         while(*p != e) p = &(*p)->next;
51         *p = e->next;
52
53         /* destroys */
54         afb_event_drop(e->event);
55         free(e);
56         return 0;
57 }
58
59 /* creates the event of tag */
60  int event_add(const char *tag, const char *name)
61 {
62         struct event *e;
63
64         /* check valid tag */
65         e = event_get(tag);
66         if (e) return -1;
67
68         /* creation */
69         e = malloc(strlen(tag) + sizeof *e);
70         if (!e) return -1;
71         strcpy(e->tag, tag);
72
73         /* make the event */
74         e->event = afb_daemon_make_event(interface->daemon, name);
75         if (!e->event.closure) { free(e); return -1; }
76
77         /* link */
78         e->next = events;
79         events = e;
80         return 0;
81 }
82
83  int event_subscribe(struct afb_req request, const char *tag)
84 {
85         struct event *e;
86         e = event_get(tag);
87         return e ? afb_req_subscribe(request, e->event) : -1;
88 }
89
90  int event_unsubscribe(struct afb_req request, const char *tag)
91 {
92         struct event *e;
93         e = event_get(tag);
94         return e ? afb_req_unsubscribe(request, e->event) : -1;
95 }
96
97  int event_push(struct json_object *args, const char *tag)
98 {
99         struct event *e;
100         e = event_get(tag);
101         return e ? afb_event_push(e->event, json_object_get(args)) : -1;
102 }
103
104 // Sample Generic Ping Debug API
105  static void ping(struct afb_req request, json_object *jresp, const char *tag)
106 {
107          static int pingcount = 0;
108         json_object *query = afb_req_json(request);
109         afb_req_success_f(request, jresp, "Ping Binder Daemon tag=%s count=%d query=%s", tag, ++pingcount, json_object_to_json_string(query));
110 }
111
112  void pingSample (struct afb_req request)
113 {
114         ping(request, json_object_new_string ("Some String"), "pingSample");
115 }
116
117  void pingFail (struct afb_req request)
118 {
119         afb_req_fail(request, "failed", "Ping Binder Daemon fails");
120 }
121
122  void pingNull (struct afb_req request)
123 {
124         ping(request, NULL, "pingNull");
125 }
126
127  void pingBug (struct afb_req request)
128 {
129         ping((struct afb_req){NULL,NULL}, NULL, "pingBug");
130 }
131
132  void pingEvent(struct afb_req request)
133 {
134         json_object *query = afb_req_json(request);
135         afb_daemon_broadcast_event(interface->daemon, "event", json_object_get(query));
136         ping(request, json_object_get(query), "event");
137 }
138
139
140 // For samples https://linuxprograms.wordpress.com/2010/05/20/json-c-libjson-tutorial/
141  void pingJson (struct afb_req request) {
142     json_object *jresp, *embed;
143
144     jresp = json_object_new_object();
145     json_object_object_add(jresp, "myString", json_object_new_string ("Some String"));
146     json_object_object_add(jresp, "myInt", json_object_new_int (1234));
147
148     embed  = json_object_new_object();
149     json_object_object_add(embed, "subObjString", json_object_new_string ("Some String"));
150     json_object_object_add(embed, "subObjInt", json_object_new_int (5678));
151
152     json_object_object_add(jresp,"eobj", embed);
153
154     ping(request, jresp, "pingJson");
155 }
156
157  void subcallcb (void *prequest, int iserror, json_object *object)
158 {
159         struct afb_req request = afb_req_unstore(prequest);
160         if (iserror)
161                 afb_req_fail(request, "failed", json_object_to_json_string(object));
162         else
163                 afb_req_success(request, object, NULL);
164         afb_req_unref(request);
165 }
166
167  void subcall (struct afb_req request)
168 {
169         const char *api = afb_req_value(request, "api");
170         const char *verb = afb_req_value(request, "verb");
171         const char *args = afb_req_value(request, "args");
172         json_object *object = api && verb && args ? json_tokener_parse(args) : NULL;
173
174         if (object == NULL)
175                 afb_req_fail(request, "failed", "bad arguments");
176         else
177                 afb_req_subcall(request, api, verb, object, subcallcb, afb_req_store(request));
178 }
179
180  void eventadd (struct afb_req request)
181 {
182         const char *tag = afb_req_value(request, "tag");
183         const char *name = afb_req_value(request, "name");
184
185         if (tag == NULL || name == NULL)
186                 afb_req_fail(request, "failed", "bad arguments");
187         else if (0 != event_add(tag, name))
188                 afb_req_fail(request, "failed", "creation error");
189         else
190                 afb_req_success(request, NULL, NULL);
191 }
192
193  void eventdel (struct afb_req request)
194 {
195         const char *tag = afb_req_value(request, "tag");
196
197         if (tag == NULL)
198                 afb_req_fail(request, "failed", "bad arguments");
199         else if (0 != event_del(tag))
200                 afb_req_fail(request, "failed", "deletion error");
201         else
202                 afb_req_success(request, NULL, NULL);
203 }
204
205  void eventsub (struct afb_req request)
206 {
207         const char *tag = afb_req_value(request, "tag");
208
209         if (tag == NULL)
210                 afb_req_fail(request, "failed", "bad arguments");
211         else if (0 != event_subscribe(request, tag))
212                 afb_req_fail(request, "failed", "subscription error");
213         else
214                 afb_req_success(request, NULL, NULL);
215 }
216
217  void eventunsub (struct afb_req request)
218 {
219         const char *tag = afb_req_value(request, "tag");
220
221         if (tag == NULL)
222                 afb_req_fail(request, "failed", "bad arguments");
223         else if (0 != event_unsubscribe(request, tag))
224                 afb_req_fail(request, "failed", "unsubscription error");
225         else
226                 afb_req_success(request, NULL, NULL);
227 }
228
229  void eventpush (struct afb_req request)
230 {
231         const char *tag = afb_req_value(request, "tag");
232         const char *data = afb_req_value(request, "data");
233         json_object *object = data ? json_tokener_parse(data) : NULL;
234
235         if (tag == NULL)
236                 afb_req_fail(request, "failed", "bad arguments");
237         else if (0 > event_push(object, tag))
238                 afb_req_fail(request, "failed", "push error");
239         else
240                 afb_req_success(request, NULL, NULL);
241 }