703 lines
21 KiB
C
703 lines
21 KiB
C
/**
|
|
* Copyright (2017) Baidu Inc. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
/**
|
|
* File: lightduer.c
|
|
* Auth: Su Hao (suhao@baidu.com)
|
|
* Desc: Light duer APIS.
|
|
*/
|
|
|
|
#include <inttypes.h>
|
|
#include "lightduer_connagent.h"
|
|
#include "lightduer_log.h"
|
|
#include "lightduer_lib.h"
|
|
#include "lightduer_adapter.h"
|
|
#include "lightduer_memory.h"
|
|
#include "lightduer_events.h"
|
|
#include "lightduer_engine.h"
|
|
#include "lightduer_ds_report.h"
|
|
#include "lightduer_ds_report_ca.h"
|
|
#include "lightduer_ds_log_ca.h"
|
|
#include "lightduer_ds_log_cache.h"
|
|
#include "lightduer_timestamp.h"
|
|
#include "lightduer_event_emitter.h"
|
|
#include "lightduer_random.h"
|
|
#include "lightduer_mutex.h"
|
|
#ifdef DUER_EVENT_HANDLER
|
|
#include "lightduer_handler.h"
|
|
#endif // DUER_EVENT_HANDLER
|
|
#include "lightduer_ap_info.h"
|
|
|
|
extern void duer_voice_initialize(void);
|
|
extern void duer_voice_finalize(void);
|
|
extern int duer_voice_terminate(void);
|
|
extern int duer_data_send(void);
|
|
extern int duer_engine_enqueue_response(
|
|
const duer_msg_t *req, int msg_code, const void *data, duer_size_t size);
|
|
extern int duer_engine_enqueue_seperate_response(
|
|
const char *token, duer_size_t token_len, int msg_code, const baidu_json *data);
|
|
extern void duer_engine_send_directly(int what, void *object);
|
|
extern void duer_session_initialize(void);
|
|
extern void duer_session_finalize(void);
|
|
|
|
static duer_event_callback g_event_callback = NULL;
|
|
|
|
#ifndef DISABLE_SPLIT_SEND
|
|
static volatile duer_u32_t s_split_id;
|
|
//used to keep the s_split_id is not negative when adding to json as int
|
|
static const int SPLIT_ID_MASK = 0x7fffffff;
|
|
static duer_mutex_t s_split_mutex;
|
|
#endif
|
|
|
|
// begin device status report
|
|
static duer_u32_t s_connect_start_time = 0;
|
|
static duer_u32_t s_connect_end_time = 0;
|
|
static duer_u32_t s_connect_count = 0;
|
|
// end device status report
|
|
|
|
// MAX num message in CA queue
|
|
#ifndef DUER_MAX_MSG_NUM_IN_CA_QUEUE
|
|
#define DUER_MAX_MSG_NUM_IN_CA_QUEUE 20
|
|
#endif //DUER_MAX_MSG_NUM_IN_CA_QUEUE
|
|
|
|
// begin whether clear the message queue
|
|
#ifndef MAX_INTERVAL_KEEP_CA_QUEUE
|
|
#define MAX_INTERVAL_KEEP_CA_QUEUE 4000 // ms
|
|
#endif // MAX_INTERVAL_KEEP_CA_QUEUE
|
|
// begin whether clear the voice data
|
|
#ifndef MAX_INTERVAL_KEEP_VOICE_QUEUE
|
|
#define MAX_INTERVAL_KEEP_VOICE_QUEUE 1900 //ms when interval > 2s,the server will stop immediately.
|
|
#endif // MAX_INTERVAL_KEEP_VOICE_QUEUE
|
|
static duer_u32_t s_first_stopped_time = 0;
|
|
|
|
#ifdef DUER_BJSON_PRINT_WITH_ESTIMATED_SIZE
|
|
#define DUER_PRINT_BJSON_ESTIMATED_SIZE_FOR_REPORT_DATA (1024)
|
|
#endif
|
|
|
|
// invoke this after CA connected
|
|
static duer_status_t duer_ca_try_clear_queue()
|
|
{
|
|
duer_u32_t current_time = duer_timestamp();
|
|
if (s_first_stopped_time > 0
|
|
&& (current_time < s_first_stopped_time
|
|
|| current_time - s_first_stopped_time > MAX_INTERVAL_KEEP_CA_QUEUE)) {
|
|
duer_clear_data(duer_timestamp());
|
|
duer_ds_log_ca_info(DUER_DS_LOG_CA_CLEAR_DATA, NULL);
|
|
}
|
|
#if !defined(__TARGET_TRACKER__)
|
|
if (s_first_stopped_time > 0
|
|
&& (current_time < s_first_stopped_time
|
|
|| current_time - s_first_stopped_time > MAX_INTERVAL_KEEP_VOICE_QUEUE)) {
|
|
duer_voice_terminate();
|
|
}
|
|
#endif
|
|
s_first_stopped_time = 0;
|
|
return DUER_OK;
|
|
}
|
|
// end whether clear the message queue
|
|
|
|
static char *g_event_name[] = {
|
|
"DUER_EVT_CREATE",
|
|
"DUER_EVT_START",
|
|
"DUER_EVT_ADD_RESOURCES",
|
|
"DUER_EVT_SEND_DATA",
|
|
"DUER_EVT_DATA_AVAILABLE",
|
|
"DUER_EVT_STOP",
|
|
"DUER_EVT_DESTROY",
|
|
"DUER_EVENTS_TOTAL"
|
|
};
|
|
|
|
static void duer_event_notify(int event_id, int event_code, void *object)
|
|
{
|
|
if (g_event_callback) {
|
|
duer_event_t event;
|
|
event._event = event_id;
|
|
event._code = event_code;
|
|
event._object = object;
|
|
g_event_callback(&event);
|
|
}
|
|
}
|
|
|
|
static void duer_set_coap_response_callback(void)
|
|
{
|
|
//duer_emitter_emit(duer_engine_set_response_callback, 0, duer_coap_response_callback);
|
|
duer_engine_set_response_callback(0, duer_coap_response_callback);
|
|
}
|
|
|
|
#ifndef DISABLE_SPLIT_SEND
|
|
static void duer_split_id_initialize()
|
|
{
|
|
if (!s_split_mutex) {
|
|
s_split_mutex = duer_mutex_create();
|
|
}
|
|
|
|
duer_mutex_lock(s_split_mutex);
|
|
s_split_id = duer_random() & SPLIT_ID_MASK;
|
|
duer_mutex_unlock(s_split_mutex);
|
|
}
|
|
|
|
static void duer_split_id_finalize()
|
|
{
|
|
if (s_split_mutex) {
|
|
duer_mutex_destroy(s_split_mutex);
|
|
s_split_mutex = NULL;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void duer_engine_notify_callback(int event, int status, int what, void *object)
|
|
{
|
|
static duer_status_t reason_to_start = DUER_OK;
|
|
duer_status_t wifi_status = DUER_OK;
|
|
|
|
if (status != DUER_OK
|
|
&& status != DUER_ERR_TRANS_WOULD_BLOCK
|
|
&& status != DUER_ERR_CONNECT_TIMEOUT
|
|
&& status != DUER_ERR_HAS_STOPPED) {
|
|
DUER_LOGI("=====> event: %d[%s], status: %d", event, g_event_name[event], status);
|
|
}
|
|
switch (event) {
|
|
case DUER_EVT_CREATE:
|
|
duer_session_initialize();
|
|
duer_set_coap_response_callback();
|
|
#ifndef DISABLE_SPLIT_SEND
|
|
duer_split_id_initialize();
|
|
#endif
|
|
break;
|
|
case DUER_EVT_START:
|
|
if (object) {
|
|
DUER_FREE(object);
|
|
}
|
|
if (status == DUER_OK) {
|
|
duer_ds_log_init();
|
|
#if !defined(__TARGET_TRACKER__)
|
|
duer_voice_initialize();
|
|
#endif
|
|
|
|
DUER_LOGI("connect started!");
|
|
duer_ca_try_clear_queue();
|
|
|
|
s_connect_end_time = duer_timestamp();
|
|
duer_u32_t connect_time_cost = (s_connect_end_time - s_connect_start_time);
|
|
duer_ds_log_ca_started(reason_to_start, s_connect_count, connect_time_cost);
|
|
s_connect_count = 0;
|
|
reason_to_start = DUER_OK;
|
|
|
|
duer_ds_log_cache_report();
|
|
|
|
duer_event_notify(DUER_EVENT_STARTED, status, NULL);
|
|
|
|
if (duer_engine_qcache_length() > 0) {
|
|
duer_data_send();
|
|
}
|
|
duer_ds_report_start(DUER_DS_PERIODIC, 0);// use the default interval
|
|
|
|
} else if (status == DUER_ERR_TRANS_WOULD_BLOCK) {
|
|
DUER_LOGI("will start latter(DUER_ERR_TRANS_WOULD_BLOCK)");
|
|
} else if (status == DUER_ERR_CONNECT_TIMEOUT) {
|
|
int rs = duer_emitter_emit(duer_engine_start, 0, NULL);
|
|
if (rs != DUER_OK) {
|
|
DUER_LOGW("retry connect fail!!");
|
|
}
|
|
} else if (status == DUER_ERR_HAS_STARTED) {
|
|
DUER_LOGW("Duer CA engine has started!");
|
|
} else {
|
|
DUER_LOGE("start fail! status:%d", status);
|
|
}
|
|
break;
|
|
case DUER_EVT_ADD_RESOURCES:
|
|
if (status == DUER_OK) {
|
|
DUER_LOGI("add resource successfully!!");
|
|
}
|
|
if (object) {
|
|
duer_res_t *resources = (duer_res_t *)object;
|
|
for (int i = 0; i < what; ++i) {
|
|
if (resources[i].path) {
|
|
DUER_FREE(resources[i].path);// more info in duer_add_resources
|
|
resources[i].path = NULL;
|
|
}
|
|
}
|
|
DUER_FREE(object);
|
|
}
|
|
break;
|
|
case DUER_EVT_SEND_DATA:
|
|
if (object) {
|
|
DUER_LOGI("data sent : %s", (const char *)object);
|
|
baidu_json_release(object);
|
|
}
|
|
//DUER_LOGI("====status:%d, len:%d=", status, duer_engine_qcache_length());
|
|
if (status >= 0) {
|
|
if (duer_engine_qcache_length() > 0) {
|
|
DUER_LOGD("###QCACHE_LEN====%d.", duer_engine_qcache_length());
|
|
duer_data_send();
|
|
}
|
|
} else if (status == DUER_ERR_TRANS_WOULD_BLOCK) {
|
|
DUER_LOGD("!!!Send WOULD_BLOCK");
|
|
} else {
|
|
//do nothing
|
|
}
|
|
break;
|
|
case DUER_EVT_DATA_AVAILABLE:
|
|
break;
|
|
case DUER_EVT_STOP:
|
|
if (status == DUER_ERR_TRANS_TIMEOUT) {
|
|
duer_clear_data(duer_timestamp());
|
|
#if !defined(__TARGET_TRACKER__)
|
|
duer_voice_terminate();
|
|
#endif
|
|
duer_ds_log_ca_info(DUER_DS_LOG_CA_CLEAR_DATA, NULL);
|
|
} else {
|
|
if (s_first_stopped_time == 0) {
|
|
s_first_stopped_time = duer_timestamp();
|
|
}
|
|
}
|
|
duer_ds_log_ca_debug(DUER_DS_LOG_CA_STOPPED, NULL);
|
|
DUER_LOGI("connect stopped, status:%d!!", status);
|
|
#if !defined(__TARGET_TRACKER__)
|
|
duer_voice_finalize();
|
|
#endif
|
|
|
|
duer_event_notify(DUER_EVENT_STOPPED, status, NULL);
|
|
break;
|
|
case DUER_EVT_DESTROY:
|
|
duer_ds_report_destroy();
|
|
duer_session_finalize();
|
|
duer_split_id_finalize();
|
|
duer_ds_log_cache_finalize();
|
|
baidu_ca_adapter_finalize();
|
|
#ifdef DUER_EVENT_HANDLER
|
|
duer_handler_destroy();
|
|
#endif // DUER_EVENT_HANDLER
|
|
#if 0 //线程不能自杀
|
|
duer_emitter_destroy();
|
|
#else
|
|
duer_emitter_request_destroy();
|
|
#endif
|
|
s_first_stopped_time = 0;
|
|
break;
|
|
default:
|
|
DUER_LOGW("unknown event!!");
|
|
break;
|
|
}
|
|
|
|
if ((event < DUER_EVT_STOP
|
|
&& status != DUER_OK
|
|
&& status != DUER_ERR_TRANS_WOULD_BLOCK
|
|
&& status != DUER_ERR_CONNECT_TIMEOUT
|
|
&& status != DUER_ERR_HAS_STARTED
|
|
&& status != DUER_ERR_HAS_STOPPED)
|
|
|| (event == DUER_EVT_STOP)) {
|
|
duer_ds_report_stop();
|
|
if (reason_to_start == DUER_OK) { // only record the first stop reason
|
|
reason_to_start = status;
|
|
wifi_status = duer_wifi_status_get();
|
|
if (wifi_status != DUER_OK && wifi_status != DUER_ERR_FAILED) {
|
|
reason_to_start = wifi_status;
|
|
}
|
|
DUER_LOGD("Wifi status: %d", wifi_status);
|
|
}
|
|
DUER_LOGE("Action failed: event: %d, status: %d", event, status);
|
|
if (event != DUER_EVT_STOP) {
|
|
duer_engine_stop(status, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
void duer_initialize()
|
|
{
|
|
baidu_ca_adapter_initialize();
|
|
|
|
duer_emitter_create();
|
|
|
|
#ifdef DUER_EVENT_HANDLER
|
|
duer_handler_create();
|
|
#endif // DUER_EVENT_HANDLER
|
|
|
|
duer_engine_register_notify(duer_engine_notify_callback);
|
|
|
|
int res = duer_emitter_emit(duer_engine_create, 0, NULL);
|
|
if (res != DUER_OK) {
|
|
DUER_LOGE("duer_initialize fail! res:%d", res);
|
|
}
|
|
|
|
int ret = duer_ds_register_report_function(duer_ds_report_ca_status);
|
|
if (ret != DUER_OK) {
|
|
DUER_LOGE("report ca status register failed ret: %d", ret);
|
|
}
|
|
|
|
duer_ds_log_cache_initialize();
|
|
|
|
duer_ds_log_ca_debug(DUER_DS_LOG_CA_INIT, NULL);
|
|
}
|
|
|
|
void duer_set_event_callback(duer_event_callback callback)
|
|
{
|
|
if (g_event_callback != callback) {
|
|
g_event_callback = callback;
|
|
}
|
|
}
|
|
|
|
int duer_start(const void *data, size_t size)
|
|
{
|
|
if (data == NULL || size == 0) {
|
|
DUER_LOGE("duer_start invalid arguments");
|
|
return DUER_ERR_INVALID_PARAMETER;
|
|
}
|
|
|
|
duer_ds_log_ca_debug(DUER_DS_LOG_CA_START, NULL);
|
|
++s_connect_count;
|
|
|
|
void *profile = DUER_MALLOC(size); // ~= 1439
|
|
|
|
if (profile == NULL) {
|
|
DUER_LOGE("memory alloc fail!");
|
|
DUER_DS_LOG_CA_MEMORY_OVERFLOW();
|
|
return DUER_ERR_MEMORY_OVERFLOW;
|
|
}
|
|
DUER_MEMCPY(profile, data, size);
|
|
DUER_LOGD("use the profile to start engine");
|
|
|
|
int rs = duer_emitter_emit(duer_engine_start, (int)size, profile);
|
|
|
|
if (rs != DUER_OK) {
|
|
DUER_LOGE("emit duer_engine_start failed!");
|
|
DUER_FREE(profile);
|
|
}
|
|
s_connect_start_time = duer_timestamp();
|
|
return rs;
|
|
}
|
|
|
|
int duer_add_resources(const duer_res_t *res, size_t length)
|
|
{
|
|
if (duer_engine_is_started() != DUER_TRUE) {
|
|
DUER_LOGW("please add control point after the CA started");
|
|
return DUER_ERR_FAILED;
|
|
}
|
|
if (length == 0 || res == NULL) {
|
|
DUER_LOGW("no resource will be added, length is 0");
|
|
return DUER_ERR_FAILED;
|
|
}
|
|
|
|
duer_bool malloc_failed = DUER_FALSE;
|
|
duer_res_t *list = (duer_res_t *)DUER_MALLOC(length * sizeof(duer_res_t)); // ~= length * 16
|
|
|
|
if (list == NULL) {
|
|
malloc_failed = DUER_TRUE;
|
|
goto malloc_fail;
|
|
}
|
|
DUER_MEMSET(list, 0, length * sizeof(duer_res_t));
|
|
for (int i = 0; i < length; ++i) {
|
|
list[i].mode = res[i].mode;
|
|
list[i].allowed = res[i].allowed;
|
|
size_t path_len = DUER_STRLEN(res[i].path);
|
|
if (list[i].mode == DUER_RES_MODE_STATIC) {
|
|
// malloc the path&static data once, Note only need free once
|
|
list[i].path = DUER_MALLOC(path_len + res[i].res.s_res.size + 1);
|
|
if (list[i].path == NULL) {
|
|
malloc_failed = DUER_TRUE;
|
|
goto malloc_fail;
|
|
}
|
|
DUER_MEMCPY(list[i].path, res[i].path, path_len);
|
|
list[i].path[path_len] = '\0';
|
|
list[i].res.s_res.size = res[i].res.s_res.size;
|
|
list[i].res.s_res.data = list[i].path + 1 + path_len;
|
|
DUER_MEMCPY(list[i].res.s_res.data, res[i].res.s_res.data, list[i].res.s_res.size);
|
|
duer_ds_log_ca_register_cp(list[i].path, DUER_CA_CP_TYPE_STATIC);
|
|
} else {
|
|
list[i].path = DUER_MALLOC(path_len + 1);
|
|
|
|
if (list[i].path == NULL) {
|
|
malloc_failed = DUER_TRUE;
|
|
goto malloc_fail;
|
|
}
|
|
DUER_MEMCPY(list[i].path, res[i].path, path_len);
|
|
list[i].path[path_len] = '\0';
|
|
list[i].res.f_res = res[i].res.f_res;
|
|
duer_ds_log_ca_register_cp(list[i].path, DUER_CA_CP_TYPE_DYNAMIC);
|
|
}
|
|
}
|
|
|
|
if (malloc_failed == DUER_FALSE) {
|
|
int rs = duer_emitter_emit(duer_engine_add_resources, (int)length, (void *)list);
|
|
if (rs == DUER_OK) {
|
|
return DUER_OK;
|
|
} else {
|
|
DUER_LOGW("add resource fail!!");
|
|
goto add_fail;
|
|
}
|
|
}
|
|
malloc_fail:
|
|
DUER_LOGW("memory malloc fail!!");
|
|
DUER_DS_LOG_CA_MEMORY_OVERFLOW();
|
|
add_fail:
|
|
if (list) {
|
|
for (int i = 0; i < length; ++i) {
|
|
if (list[i].path) {
|
|
DUER_FREE(list[i].path);
|
|
list[i].path = NULL;
|
|
}
|
|
}
|
|
DUER_FREE(list);
|
|
list = NULL;
|
|
}
|
|
return DUER_ERR_FAILED;
|
|
}
|
|
|
|
int duer_data_send(void)
|
|
{
|
|
//DUER_LOGI("===%s===", __func__);
|
|
return duer_emitter_emit(duer_engine_send, 0, NULL);
|
|
}
|
|
|
|
static int duer_data_real_send(void)
|
|
{
|
|
//DUER_LOGI("===%s===", __func__);
|
|
return duer_emitter_emit(duer_engine_send_directly, 0, NULL);
|
|
}
|
|
|
|
static int duer_after_enqueue_handler(int rs)
|
|
{
|
|
if (rs > 0) {
|
|
if (rs == 1) {
|
|
rs = duer_data_send();
|
|
} else if (rs > 10) {
|
|
DUER_LOGW("cached more than 10 message!!");
|
|
rs = duer_data_real_send();
|
|
} else {
|
|
rs = DUER_OK;
|
|
}
|
|
}
|
|
return rs;
|
|
}
|
|
|
|
#ifndef DISABLE_SPLIT_SEND
|
|
static int duer_copy_split_data(char *des, int size, char *source)
|
|
{
|
|
int des_str_len = 0;
|
|
int special_char_count = 0;
|
|
|
|
if (!des || !source || size <= 0) {
|
|
DUER_LOGE("Invalid param");
|
|
return 0;
|
|
}
|
|
|
|
while (source[des_str_len] != '\0') {
|
|
if ((source[des_str_len] == '\"') || (source[des_str_len] == '\\')) {
|
|
special_char_count++;
|
|
}
|
|
if (des_str_len + special_char_count + 1 >= size - 1) {
|
|
break;
|
|
}
|
|
des[des_str_len] = source[des_str_len];
|
|
des_str_len++;
|
|
}
|
|
|
|
des[des_str_len] = '\0';
|
|
|
|
return des_str_len;
|
|
}
|
|
|
|
static int duer_data_get_split_id()
|
|
{
|
|
duer_u32_t ret = 0;
|
|
|
|
duer_mutex_lock(s_split_mutex);
|
|
s_split_id = (s_split_id + 1) & SPLIT_ID_MASK;
|
|
ret = s_split_id;
|
|
duer_mutex_unlock(s_split_mutex);
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
int duer_data_report_async(duer_context_t *context, const baidu_json *data)
|
|
{
|
|
#ifdef DISABLE_SPLIT_SEND
|
|
int rs = duer_engine_enqueue_report_data(context, data);
|
|
//DUER_LOGI("===%s===, context:%p, rs:%d", __func__, context, rs);
|
|
return duer_after_enqueue_handler(rs);
|
|
#else
|
|
int rs = DUER_OK;
|
|
int block = 0;
|
|
int content_len = 0;
|
|
int send_len = 0;
|
|
int remain_len = 0;
|
|
duer_u32_t id = 0;
|
|
const int MAX_SEG_LEN = 990;
|
|
const int MAX_PAYLOAD_LEN = 900;
|
|
char *buf = NULL;
|
|
char *content = NULL;
|
|
baidu_json *value = NULL;
|
|
baidu_json *payload = NULL;
|
|
|
|
do {
|
|
#ifdef DUER_BJSON_PRINT_WITH_ESTIMATED_SIZE
|
|
content = baidu_json_PrintBuffered(data,
|
|
DUER_PRINT_BJSON_ESTIMATED_SIZE_FOR_REPORT_DATA, 0);
|
|
#else
|
|
content = baidu_json_PrintUnformatted(data);
|
|
#endif // DUER_BJSON_PRINT_WITH_ESTIMATED_SIZE
|
|
id = duer_data_get_split_id();
|
|
if (!content) {
|
|
rs = DUER_ERR_MEMORY_OVERFLOW;
|
|
break;
|
|
}
|
|
content_len = DUER_STRLEN(content);
|
|
if (content_len <= MAX_SEG_LEN) {
|
|
baidu_json_release(content);
|
|
content = NULL;
|
|
rs = duer_engine_enqueue_report_data(context, data);
|
|
//DUER_LOGI("===%s===, context:%p, rs:%d", __func__, context, rs);
|
|
rs = duer_after_enqueue_handler(rs);
|
|
break;
|
|
}
|
|
|
|
DUER_LOGD("split send data, %d", content_len);
|
|
|
|
buf = DUER_MALLOC(MAX_PAYLOAD_LEN + 1); // ~= 901
|
|
if (!buf) {
|
|
rs = DUER_ERR_MEMORY_OVERFLOW;
|
|
break;
|
|
}
|
|
|
|
value = baidu_json_CreateObject();
|
|
if (!value) {
|
|
rs = DUER_ERR_MEMORY_OVERFLOW;
|
|
break;
|
|
}
|
|
|
|
payload = baidu_json_CreateObject();
|
|
if (!payload) {
|
|
rs = DUER_ERR_MEMORY_OVERFLOW;
|
|
break;
|
|
}
|
|
baidu_json_AddItemToObjectCS(value, "duer_blockwise", payload);
|
|
baidu_json_AddNumberToObjectCS(payload, "id", (int)id);
|
|
baidu_json_AddNumberToObjectCS(payload, "eof", 0);
|
|
remain_len = content_len;
|
|
|
|
while (remain_len > 0) {
|
|
baidu_json_DeleteItemFromObject(payload, "block");
|
|
baidu_json_AddNumberToObjectCS(payload, "block", block++);
|
|
send_len = duer_copy_split_data(buf,
|
|
MAX_PAYLOAD_LEN + 1,
|
|
content + content_len - remain_len);
|
|
if (send_len == 0) {
|
|
rs = DUER_ERR_FAILED;
|
|
break;
|
|
}
|
|
|
|
DUER_LOGD("remain_len:%d, block:%d, send_len:%d", remain_len, block, send_len);
|
|
|
|
remain_len -= send_len;
|
|
if (remain_len == 0) {
|
|
baidu_json_DeleteItemFromObject(payload, "eof");
|
|
baidu_json_AddNumberToObjectCS(payload, "eof", 1);
|
|
}
|
|
baidu_json_DeleteItemFromObject(payload, "block_data");
|
|
baidu_json_AddStringToObjectCS(payload, "block_data", buf);
|
|
|
|
rs = duer_engine_enqueue_report_data(context, value);
|
|
//DUER_LOGI("===%s===, context:%p, rs:%d", __func__, context, rs);
|
|
rs = duer_after_enqueue_handler(rs);
|
|
//sleep needed if the invoke thread has the same priority with lightduer_ca,
|
|
//sleep can trigger lightduer_ca to do the real send work
|
|
//#include "lightduer_sleep.h"
|
|
//duer_sleep(1);
|
|
if (rs != DUER_OK) {
|
|
break;
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
if (content) {
|
|
baidu_json_release(content);
|
|
}
|
|
|
|
if (buf) {
|
|
DUER_FREE(buf);
|
|
}
|
|
|
|
if (value) {
|
|
baidu_json_Delete(value);
|
|
}
|
|
|
|
return rs;
|
|
#endif
|
|
}
|
|
|
|
int duer_data_report(const baidu_json *data)
|
|
{
|
|
if (duer_engine_qcache_length() > DUER_MAX_MSG_NUM_IN_CA_QUEUE) {
|
|
DUER_LOGW("CA queue max num(%d) reached!", DUER_MAX_MSG_NUM_IN_CA_QUEUE);
|
|
return DUER_ERR_FAILED;
|
|
}
|
|
return duer_data_report_async(NULL, data);
|
|
}
|
|
|
|
int duer_response(const duer_msg_t *msg, int msg_code, const void *data, duer_size_t size)
|
|
{
|
|
int rs = duer_engine_enqueue_response(msg, msg_code, data, size);
|
|
//DUER_LOGI("===%s=== rs:%d", __func__, rs);
|
|
return duer_after_enqueue_handler(rs);
|
|
}
|
|
|
|
int duer_seperate_response(const char *token,
|
|
duer_size_t token_len,
|
|
int msg_code,
|
|
const baidu_json *data)
|
|
{
|
|
int rs = duer_engine_enqueue_seperate_response(token, token_len, msg_code, data);
|
|
|
|
return duer_after_enqueue_handler(rs);
|
|
}
|
|
|
|
int duer_data_available()
|
|
{
|
|
return duer_emitter_emit(duer_engine_data_available, 0, NULL);
|
|
}
|
|
|
|
int duer_clear_data(duer_u32_t timestamp)
|
|
{
|
|
return duer_emitter_emit((duer_events_func)duer_engine_clear_data, timestamp, NULL);
|
|
}
|
|
|
|
int duer_stop()
|
|
{
|
|
return duer_emitter_emit(duer_engine_stop, 0, NULL);
|
|
}
|
|
|
|
int duer_stop_with_reason(int reason)
|
|
{
|
|
return duer_emitter_emit(duer_engine_stop, reason, NULL);
|
|
}
|
|
|
|
void duer_coap_response_callback(duer_context ctx,
|
|
duer_msg_t *msg,
|
|
duer_addr_t *addr)
|
|
{
|
|
// to handle response with unauthorized code 129 = 0x81(4.01)
|
|
if (msg->msg_type == DUER_MSG_TYPE_ACKNOWLEDGEMENT
|
|
&& msg->msg_code == DUER_MSG_RSP_UNAUTHORIZED) {
|
|
// try to stop CA
|
|
DUER_LOGW("DUER_MSG_RSP_UNAUTHORIZED code for coap ACK message, try to stop");
|
|
duer_stop_with_reason(DUER_MSG_RSP_UNAUTHORIZED);
|
|
}
|
|
}
|
|
|
|
int duer_finalize(void)
|
|
{
|
|
return duer_emitter_emit(duer_engine_destroy, 0, NULL);
|
|
}
|