Add a logic for sending and receiving JSON data
[platform/core/uifw/capi-ui-sticker.git] / receiver / src / ft.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <glib.h>
19 #include <dlog.h>
20 #include <service_app.h>
21 #include <app_common.h>
22 #include <sap.h>
23 #include <sap_file_transfer.h>
24 #include <sticker_provider.h>
25 #include <string.h>
26 #include <string>
27 #include <unistd.h>
28 #include <linux/limits.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <pwd.h>
32 #include <json-glib/json-glib.h>
33
34 #include "ft.h"
35 #include "log.h"
36 #include "sticker_info.h"
37
38 #define ACCESSORY_SERVICE_PROFILE_ID "/sample/filetransfersender"
39 #define ACCESSORY_SERVICE_CHANNEL_ID 107
40
41 #define STICKER_SYNC_START_REQ "sticker-sync-start-req"
42 #define STICKER_SYNC_START_RSP "sticker-sync-start-rsp"
43 #define STICKER_SEND_START_REQ "sticker-send-start-req"
44 #define STICKER_SEND_START_RSP "sticker-send-start-rsp"
45 #define STICKER_SEND_FACE_DATA "sticker-send-face-data"
46 #define STICKER_SEND_STOP_REQ  "sticker-send-stop-req"
47 #define STICKER_SEND_STOP_RSP  "sticker-send-stop-rsp"
48
49 using namespace std;
50
51 struct priv {
52     sap_agent_h agent;
53     sap_socket_h socket;
54     sap_file_transaction_h file_socket;
55 };
56
57 static void _reset_sticker_data();
58
59 struct sticker_info {
60     string file_path;
61     string group;
62     string keyword;
63     string disp_type;
64     string description;
65
66     sticker_info()
67     {
68         _reset_sticker_data();
69     }
70 };
71
72 static struct priv priv_data = { 0 };
73 static struct sticker_info sticker_data;
74
75 gboolean file_on_progress = 0;
76 static string incoming_file_name;
77 static int t_id = 0;
78 static int rec_file_cnt = 0;
79
80 static gboolean _send_json_data(JsonObject *obj)
81 {
82     JsonGenerator *j_generator = NULL;
83     JsonNode *j_node = NULL;
84     gsize size = 0;
85     gchar *data = NULL;
86     int result = 1;
87
88     j_generator = json_generator_new();
89     if (j_generator == NULL) {
90         LOGE("Unable to json_generator_new");
91         goto cleanup;
92     }
93
94     j_node = json_node_new(JSON_NODE_OBJECT);
95     if (j_node == NULL) {
96         LOGE("Unable to json_node_new");
97         goto cleanup;
98     }
99
100     json_node_set_object(j_node, obj);
101     json_generator_set_root(j_generator, j_node);
102
103     data = json_generator_to_data(j_generator, &size);
104     if (data == NULL) {
105         LOGE("Unable to json_generator_to_data");
106         goto cleanup;
107     }
108
109     if (priv_data.socket) {
110         LOGD("Send JSON data : %s", data);
111         result = sap_socket_send_data(priv_data.socket, ACCESSORY_SERVICE_CHANNEL_ID, strlen(data), (void *)data);
112     }
113
114 cleanup:
115     if (data)
116         g_free(data);
117
118     if (j_node)
119         json_node_free(j_node);
120
121     if (j_generator)
122         g_object_unref(j_generator);
123
124     return result ? FALSE : TRUE;
125 }
126
127 static void _on_send_completed(sap_file_transaction_h file_transaction,
128                                sap_ft_transfer_e result,
129                                const char *file_path,
130                                void *user_data)
131 {
132     if (priv_data.file_socket) {
133         sap_file_transfer_destroy(file_transaction);
134         priv_data.file_socket = NULL;
135     }
136
137     if (result == SAP_FT_TRANSFER_SUCCESS) {
138         LOGI("Transfer Completed");
139
140         if (chmod(sticker_data.file_path.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
141             LOGE("Failed to change permission : %s. error : %s", sticker_data.file_path.c_str(), strerror(errno));
142         }
143         else {
144             LOGI("Succeed to change permission : %s", sticker_data.file_path.c_str());
145             if (create_sticker_provider_handle() == STICKER_ERROR_NONE) {
146                 insert_sticker_data(sticker_data.file_path.c_str(), sticker_data.keyword.c_str(), sticker_data.group.c_str(), sticker_data.description.c_str());
147                 destroy_sticker_provider_handle();
148
149                 if (unlink(sticker_data.file_path.c_str()) == -1)
150                     LOGE("Failed to remove sticker file");
151             }
152         }
153
154         rec_file_cnt++;
155     } else {
156         switch (result) {
157             case (SAP_FT_TRANSFER_FAIL_CHANNEL_IO): {
158                 LOGW("Channel IO Error.");
159                 break;
160             }
161
162             case (SAP_FT_TRANSFER_FAIL_FILE_IO): {
163                 LOGW("File IO Error.");
164                 break;
165             }
166
167             case (SAP_FT_TRANSFER_FAIL_CMD_DROPPED):
168             {
169                 LOGW("Transfer dropped.");
170                 break;
171             }
172
173             case (SAP_FT_TRANSFER_FAIL_PEER_UNRESPONSIVE):
174             {
175                 LOGW("Peer Un Responsive.");
176                 break;
177             }
178
179             case (SAP_FT_TRANSFER_FAIL_PEER_CONN_LOST):
180             {
181                 LOGW("Connection Lost.");
182                 break;
183             }
184
185             case (SAP_FT_TRANSFER_FAIL_PEER_CANCELLED):
186             {
187                 LOGW("Peer Cancelled.");
188                 break;
189             }
190
191             case (SAP_FT_TRANSFER_FAIL_SPACE_NOT_AVAILABLE):
192             {
193                 LOGW("No Space.");
194                 break;
195             }
196
197             default:
198                 LOGW("Unknown Error");
199                 break;
200         }
201     }
202
203     file_on_progress = 0;
204 }
205
206 static void _on_sending_file_in_progress(sap_file_transaction_h file_transaction,
207                                          unsigned short int percentage_progress,
208                                          void *user_data)
209 {
210     LOGI("# progress %d", percentage_progress);
211 }
212
213 static void __set_file_transfer_cb(sap_file_transaction_h file_socket)
214 {
215     LOGI("# set callbacks");
216     sap_file_transfer_set_progress_cb(file_socket, _on_sending_file_in_progress, NULL);
217
218     sap_file_transfer_set_done_cb(file_socket, _on_send_completed, NULL);
219 }
220
221 void accept_file()
222 {
223     int ret;
224     char file_path[PATH_MAX];
225     char *data_path = NULL;
226
227     data_path = app_get_shared_data_path();
228     LOGI("Path : %s", data_path);
229     sprintf(file_path, "%s/%s", data_path, incoming_file_name.c_str());
230     LOGI("Receive filepath : %s", file_path);
231     sticker_data.file_path = string(file_path);
232     free(data_path);
233
234     ret = sap_file_transfer_receive(priv_data.file_socket, file_path);
235     switch(ret) {
236         case SAP_RESULT_PERMISSION_DENIED:
237             LOGW("permission denied");
238             break;
239         case SAP_RESULT_FAILURE:
240             LOGW("Fail");
241             break;
242         case SAP_RESULT_SUCCESS:
243             LOGI("Success");
244             break;
245     }
246
247     file_on_progress = 1;
248 }
249
250 void sap_file_transfer_get_receive_filepath(char **filepath)
251 {
252     *filepath = strdup(sticker_data.file_path.c_str());
253 }
254
255 void request_sticker_data(const char *mode, const char *category, const char *type)
256 {
257     JsonObject *j_object = json_object_new();
258     if (j_object == NULL) {
259         LOGE("json object create error");
260         return;
261     }
262
263     json_object_set_string_member(j_object, "msgId", STICKER_SYNC_START_REQ);
264     json_object_set_int_member(j_object, "tID", ++t_id);
265     json_object_set_string_member(j_object, "mode", mode);
266     json_object_set_string_member(j_object, "category", category);
267     json_object_set_string_member(j_object, "type", type);
268
269     if (_send_json_data(j_object) == FALSE)
270         LOGE("Failed to request sticker data");
271
272     json_object_unref(j_object);
273 }
274
275 void reject_file()
276 {
277     int ret = sap_file_transfer_reject(priv_data.file_socket);
278     LOGI("ret : %d", ret);
279
280     file_on_progress = 0;
281 }
282
283 static void _on_receive_file_cb(sap_peer_agent_h peer_agent_h,
284                                 sap_file_transaction_h socket,
285                                 const char *file_path,
286                                 void *user_data)
287 {
288     file_on_progress = 1;
289     priv_data.file_socket = socket;
290     LOGI("# incoming file request.");
291     __set_file_transfer_cb(priv_data.file_socket);
292
293     incoming_file_name = file_path;
294     std::size_t found = incoming_file_name.find_last_of("/");
295     incoming_file_name = incoming_file_name.substr(found+1);
296
297     LOGI("# file path : %s, incoming file name : %s", file_path, incoming_file_name.c_str());
298
299     accept_file();
300 }
301
302 void conn_terminated(sap_peer_agent_h peer_agent,
303                      sap_socket_h socket,
304                      sap_service_connection_terminated_reason_e result,
305                      void *user_data)
306 {
307     switch (result)
308     {
309     case SAP_CONNECTION_TERMINATED_REASON_PEER_DISCONNECTED:
310         LOGW("Peer Disconnected");
311         break;
312     case SAP_CONNECTION_TERMINATED_REASON_DEVICE_DETACHED:
313         LOGW("Disconnected Device Detached");
314         break;
315     case SAP_CONNECTION_TERMINATED_REASON_UNKNOWN:
316         LOGW("Disconnected Unknown Reason");
317         break;
318     default:
319         LOGW("connection terminated. reason : %d", result);
320         break;
321     }
322
323     service_app_exit();
324 }
325
326 static void _reset_sticker_data()
327 {
328     sticker_data.file_path.clear();
329     sticker_data.group.clear();
330     sticker_data.keyword.clear();
331     sticker_data.disp_type.clear();
332     sticker_data.description.clear();
333 }
334
335 void
336 on_data_received(sap_socket_h socket, unsigned short int channel_id, unsigned int payload_length, void *buffer,
337                  void *user_data) /* message exchange on_receive callback (sap_agent_data_received_cb) */
338 {
339     LOGI("received data: %s, len:%d", (char *)buffer, payload_length);
340
341     JsonParser *parser = json_parser_new();
342     GError *err_msg = NULL;
343     JsonNode *root = NULL;
344     JsonObject *root_obj = NULL;
345     string msg_id;
346     const char *json_msgid = NULL;
347
348     json_parser_load_from_data(parser, (char *)buffer, -1, &err_msg);
349     if (err_msg) {
350         LOGE("failed to load json file. error message: %s", err_msg->message);
351         goto cleanup;
352     }
353
354     root = json_parser_get_root(parser);
355     if (root == NULL) {
356         LOGE("failed to get root");
357         goto cleanup;
358     }
359
360     root_obj = json_node_get_object(root);
361     if (root_obj == NULL) {
362         LOGE("failed to get object");
363         goto cleanup;
364     }
365
366     json_msgid = json_object_get_string_member(root_obj, "msgId");
367     msg_id = string(json_msgid ? json_msgid : "");
368     if (msg_id == STICKER_SYNC_START_RSP) {
369         LOGD("msg : %s", msg_id.c_str());
370         const char *json_result = json_object_get_string_member(root_obj, "result");
371         string result = string(json_result ? json_result : "");
372         int result_code = json_object_get_int_member(root_obj, "resultCode");
373         LOGD("result : %s, resultCode : %d", result.c_str(), result_code);
374     } else if (msg_id == STICKER_SEND_START_REQ) {
375         LOGD("msg : %s", msg_id.c_str());
376         rec_file_cnt = 0;
377         t_id = json_object_get_int_member(root_obj, "tID");
378         JsonArray *file_list = json_object_get_array_member(root_obj, "list");
379         if (file_list) {
380             int arr_len = json_array_get_length(file_list);
381             for (int i = 0; i < arr_len; i++) {
382                 JsonObject *file_obj = json_array_get_object_element(file_list, i);
383                 int file_len = json_object_get_int_member(file_obj, "size");
384                 const char *json_filename = json_object_get_string_member(file_obj, "fileName");
385                 string file_name = string(json_filename ? json_filename : "");
386
387                 if (file_len > 0) {
388                     LOGD("fileName : %s, len : %d", file_name.c_str(), file_len);
389                 } else {
390                     // Delete sticker
391                     LOGD("fileName : %s, len : %d", file_name.c_str(), file_len);
392                 }
393             }
394         }
395
396         JsonObject *j_object = json_object_new();
397         if (j_object == NULL) {
398             LOGE("Unable to json_object_new");
399             goto cleanup;
400         }
401
402         json_object_set_string_member(j_object, "msgId", STICKER_SEND_START_RSP);
403         json_object_set_int_member(j_object, "tID", t_id);
404         json_object_set_string_member(j_object, "result", "success");
405
406         if (_send_json_data(j_object) == FALSE)
407             LOGE("Failed to send message");
408
409         json_object_unref(j_object);
410     } else if (msg_id == STICKER_SEND_FACE_DATA) {
411         LOGD("msg : %s", msg_id.c_str());
412         _reset_sticker_data();
413
414         const char *type_data = json_object_get_string_member(root_obj, "type");
415         if (type_data)
416             sticker_data.disp_type = string(type_data);
417
418         const char *category = json_object_get_string_member(root_obj, "category");
419         if (category) {
420             sticker_data.group = string(category);
421             sticker_data.keyword = string(category);
422         }
423     } else if (msg_id == STICKER_SEND_STOP_REQ) {
424         LOGD("msg : %s", msg_id.c_str());
425         const char *json_reason = json_object_get_string_member(root_obj, "reason");
426         string reason = string(json_reason ? json_reason : "");
427         int file_len = json_object_get_int_member(root_obj, "count");
428
429         JsonObject *j_object = json_object_new();
430         if (j_object == NULL) {
431             LOGE("Unable to json_object_new");
432             goto cleanup;
433         }
434
435         json_object_set_string_member(j_object, "msgId", STICKER_SEND_STOP_RSP);
436         json_object_set_int_member(j_object, "tID", t_id);
437
438         if (reason == "complete" && rec_file_cnt != file_len)
439             json_object_set_string_member(j_object, "result", "failure");
440         else
441             json_object_set_string_member(j_object, "result", "success");
442
443         if (_send_json_data(j_object) == FALSE)
444             LOGE("Failed to send message");
445
446         json_object_unref(j_object);
447     } else
448         LOGW("unknown msg id : %s", msg_id.c_str());
449
450 cleanup:
451     if (err_msg)
452         g_error_free(err_msg);
453
454     if (parser)
455         g_object_unref(parser);
456 }
457
458 static void on_conn_req(sap_peer_agent_h peer_agent,
459                         sap_socket_h socket,
460                         sap_service_connection_result_e result,
461                         void *user_data)
462 {
463     if (result == SAP_CONNECTION_SUCCESS) {
464         priv_data.socket = socket;
465         sap_peer_agent_accept_service_connection(peer_agent);
466         sap_peer_agent_set_service_connection_terminated_cb(peer_agent, conn_terminated, NULL);
467         sap_socket_set_data_received_cb(socket, on_data_received, peer_agent);
468     }
469 }
470
471 static void on_agent_initialized(sap_agent_h agent,
472                                  sap_agent_initialized_result_e result,
473                                  void *user_data)
474 {
475     switch (result) {
476         case SAP_AGENT_INITIALIZED_RESULT_SUCCESS:
477             LOGD("agent is initialized");
478
479             priv_data.agent = agent;
480
481             sap_file_transfer_set_incoming_file_cb(agent, _on_receive_file_cb, NULL);
482             sap_agent_set_service_connection_requested_cb(agent, on_conn_req, NULL);
483
484             break;
485         case SAP_AGENT_INITIALIZED_RESULT_DUPLICATED:
486             LOGE("duplicate registration");
487             break;
488         case SAP_AGENT_INITIALIZED_RESULT_INVALID_ARGUMENTS:
489             LOGE("invalid arguments");
490             break;
491         case SAP_AGENT_INITIALIZED_RESULT_INTERNAL_ERROR:
492             LOGE("internal sap error");
493             break;
494         default:
495             LOGE("unknown status (%d)", result);
496             break;
497     }
498 }
499
500 static void on_agent_deinitialized(sap_agent_h agent,
501                                    sap_agent_deinitialized_result_e result,
502                                    void *user_data)
503 {
504     LOGD("result of deinitialize : %d", result);
505 }
506
507 static void _on_device_status_changed(sap_device_status_e status,
508                                       sap_transport_type_e transport_type,
509                                       void *user_data)
510 {
511     LOGD("%s, status :%d", __func__, status);
512
513     switch (transport_type) {
514         case SAP_TRANSPORT_TYPE_BT:
515             LOGD("transport_type (%d): bt", transport_type);
516             break;
517         case SAP_TRANSPORT_TYPE_BLE:
518             LOGD("transport_type (%d): ble", transport_type);
519             break;
520         case SAP_TRANSPORT_TYPE_TCP:
521             LOGD("transport_type (%d): tcp/ip", transport_type);
522             break;
523         case SAP_TRANSPORT_TYPE_USB:
524             LOGD("transport_type (%d): usb", transport_type);
525             break;
526         case SAP_TRANSPORT_TYPE_MOBILE:
527             LOGD("transport_type (%d): mobile", transport_type);
528             break;
529         default:
530             LOGE("unknown transport_type (%d)", transport_type);
531             break;
532     }
533
534     switch (status) {
535         case SAP_DEVICE_STATUS_DETACHED:
536             LOGD("device is not connected.");
537             break;
538         case SAP_DEVICE_STATUS_ATTACHED:
539             LOGD("Attached calling find peer now");
540             break;
541         default:
542             LOGE("unknown status (%d)", status);
543             break;
544     }
545 }
546
547 gboolean agent_initialize()
548 {
549     int result = 0;
550
551     do {
552         result = sap_agent_initialize(priv_data.agent, ACCESSORY_SERVICE_PROFILE_ID, SAP_AGENT_ROLE_CONSUMER,
553                 on_agent_initialized, NULL);
554
555         LOGD("SAP >>> getRegisteredServiceAgent() >>> %d", result);
556     } while (result != SAP_RESULT_SUCCESS);
557
558     return TRUE;
559 }
560
561 gboolean initialize_sap(void)
562 {
563     sap_agent_h agent = NULL;
564
565     sap_agent_create(&agent);
566
567     priv_data.agent = agent;
568
569     agent_initialize();
570
571     sap_set_device_status_changed_cb(_on_device_status_changed, NULL);
572
573     return TRUE;
574 }
575
576 void deinitialize_sap(void)
577 {
578     if (priv_data.agent) {
579         int ret = sap_agent_deinitialize(priv_data.agent, on_agent_deinitialized, NULL);
580         switch (ret) {
581             case SAP_RESULT_FAILURE:
582                 LOGW("Failed to deinitialize");
583                 break;
584             case SAP_RESULT_SUCCESS:
585                 LOGD("Succeed to deinitialize");
586                 break;
587             case SAP_RESULT_PERMISSION_DENIED:
588                 LOGW("permission denied: deinitialize ");
589                 break;
590             default:
591                 LOGD("deinitialize : %d", ret);
592                 break;
593         }
594
595         sap_agent_destroy(priv_data.agent);
596         priv_data.agent = NULL;
597     }
598 }