Files
BPI-CM9-Linux/aml-comp/vendor/amlogic/ccdatabase/server/dataserver_inner.c
T
2026-08-24 10:03:24 +08:00

398 lines
8.8 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <sys/prctl.h>
#include "dataserver_rb.h"
#include "dataserver_reader.h"
#include "dataserver_reader_inner.h"
#include "dataserver_message.h"
#include "dataserver_process.h"
#include "dataserver_utils.h"
#include "dataserver_inner.h"
#include "list.h"
#ifdef LOG_LOGCAT
#define LOG_TAG "ccdataserver"
#include <log/log.h>
#define ds_inf(_fmt_,...) ALOGI("%s:%d "_fmt_, __func__, __LINE__, ##__VA_ARGS__)
#define ds_err(_fmt_,...) ALOGE("%s:%d "_fmt_, __func__, __LINE__, ##__VA_ARGS__)
#else
#define ds_inf(_fmt_,...) printf("I %s:%d "_fmt_"\n", __func__, __LINE__, ##__VA_ARGS__)
#define ds_err(_fmt_,...) printf("E %s:%d "_fmt_"\n", __func__, __LINE__, ##__VA_ARGS__)
#endif
/*ret:
* -1: next
* -3: error
*/
int ds_connection_manage_data_in(ds_connection_t *conn)
{
/*Assume the size is no more than these values*/
#define MAX_MESSAGE_SIZE 1024
#define MAX_RESP_SIZE 1024
uint8_t buf[MAX_MESSAGE_SIZE];
uint8_t b_resp[MAX_RESP_SIZE];
int ret = 0;
int n;
n = conn->read(conn, buf, sizeof(ds_msg_head_t));
if (n < 0)
return -3;
if (n == 0)
return -1;
if (n != sizeof(ds_msg_head_t)) {
ds_err("invalid msg, ignore. n[%d]", n);
return -1;
}
ds_msg_head_t *h = (ds_msg_head_t *)buf;
char s[64];
d2s(s, sizeof(s), (uint8_t *)&h->magic, 4);
ds_inf("sess[%p] fd[%d]: recv(%d) msg[m:%s t:%d, l:%d]",
conn, conn->fd, n, s, h->type, h->size);
n = conn->read(conn, h->body, h->size);
if (n < 0)
return -3;
if (n != h->size) {
ds_err("invalid msg, ignore");
return -1;
}
switch (h->type) {
case DS_T_CNTL:
ret = process_control_msg(conn, h->body, h->size, b_resp, sizeof(b_resp));
if (ret) {
ds_msg_head_t h_resp = {
.magic = DS_MAGIC,
.type = DS_T_RESP,
.size = ret,
};
ret = conn->write(conn, &h_resp, sizeof(h_resp));
if (ret < 0)
return -3;
ret = conn->write(conn, b_resp, h_resp.size);
if (ret < 0)
return -3;
} else {
ds_err("[ERROR] failed to process control msg");
strcpy((char *)b_resp, "ko");
ds_msg_head_t h_resp = {
.magic = DS_MAGIC,
.type = DS_T_RESP,
.size = 3,
};
ret = conn->write(conn, &h_resp, sizeof(h_resp));
if (ret < 0)
return -3;
ret = conn->write(conn, b_resp, h_resp.size);
if (ret < 0)
return -3;
}
break;
case DS_T_RESP:
ret = process_response_msg(conn, h->body, h->size);
break;
case DS_T_EVNT:
ret = process_event_msg(conn, h->body, h->size);
break;
case DS_T_DATA:
ret = process_data_msg(conn, h->body, h->size);
break;
case 0x80:/*request disconnect*/
ds_inf("data in break due to exit requested");
return -3;
default:
ds_err("unknown msg type[%d]", h->type);
break;
}
return 0;
}
/*ret:
* -1: next
* -3: error
*/
int ds_connection_manage_data_out(ds_connection_t *conn)
{
#define DS_CONN_BUF_MAX_SIZE (1024 * 5 + 128)
int flag = ds_rb_get_flag_timeout(&conn->rb, 10/*timeout:10ms*/);
if (flag & DS_RB_FLAG_EXIT) {
ds_inf("data out break due to exit requested");
return 0;
}
if (!(flag & DS_RB_FLAG_READY))
return -1;
if (!(flag & DS_RB_FLAG_OVERFLOW)) {
size_t size = 0;
if (flag & DS_RB_FLAG_BLOCK) {/*block mode*/
size_t bs = 0;
int ret = ds_rb_dequeue_block(&conn->rb, &bs);
if (ret == 0 && bs > 0) {
ssize_t avai = ds_rb_avail(&conn->rb);
if (avai < size) {
ds_err("avai(%zd) < bs(%zu), something incorrect",
avai, size);
return -3;
}
size = bs;
if (size > DS_CONN_BUF_MAX_SIZE) {
ds_err("DS_CONN_BUF_MAX_SIZE(%d) is not suitable for block mode, meet(%zd)",
DS_CONN_BUF_MAX_SIZE, size);
return -3;
}
}
} else {//stream mode
size = ds_rb_avail(&conn->rb);
if (size > DS_CONN_BUF_MAX_SIZE)
size = DS_CONN_BUF_MAX_SIZE;
}
if (size) {
if (!conn->buf) {
conn->buf = (uint8_t *)malloc(DS_CONN_BUF_MAX_SIZE);
if (!conn->buf) {
ds_err("memory fail");
return -3;
}
}
ds_rb_read(&conn->rb, conn->buf, size);
ds_msg_head_t h_data = {
.magic = DS_MAGIC,
.type = DS_T_DATA,
.size = size,
};
int ret = conn->write(conn, &h_data, sizeof(h_data));
if (ret < 0)
return -3;
ret = conn->write(conn, conn->buf, size);
if (ret < 0)
return -3;
conn->data_cnt_out += size;
}
} else {
char s_overflow[] = "rb_overflow";
ds_msg_head_t h_evnt = {
.magic = DS_MAGIC,
.type = DS_T_EVNT,
.size = sizeof(s_overflow),
};
int ret = conn->write(conn, &h_evnt, sizeof(h_evnt));
if (ret < 0)
return -3;
ret = conn->write(conn, s_overflow, h_evnt.size);
if (ret < 0)
return -3;
}
return 0;
}
static void _ds_conn_lock(void *g, int lock)
{
ds_connection_t *conn = (ds_connection_t *)g;
if (lock)
pthread_mutex_lock(&conn->lock);
else
pthread_mutex_unlock(&conn->lock);
}
ds_connection_t* ds_connection_create(void)
{
ds_connection_t *conn =
(ds_connection_t *)calloc(1, sizeof(ds_connection_t));
if (conn) {
INIT_LIST_HEAD(&conn->controls);
pthread_mutex_init(&conn->lock, NULL);
ds_rb_init_lock(&conn->rb, _ds_conn_lock, conn);
return conn;
}
return NULL;
}
int ds_connection_start(ds_server_t *server, ds_connection_t *conn, void *priv)
{
int ret = 0;
conn->server = server;
if (conn->init)
ret = conn->init(conn, priv);
if (ret != 0)
return -1;
if (conn->start) {
conn->active = 1;
conn->wr_active = 1;
conn->rd_active = 1;
ret = conn->start(conn);
}
if (ret == 0) {
list_add_tail(&conn->head, &server->conns);
} else {
conn->active = 0;
conn->wr_active = 0;
conn->rd_active = 0;
if (conn->deinit)
conn->deinit(conn);
free(conn);
ds_err("connection fd[%d], failed to start session due to thread failure, err(%d)",
server->fd, ret);
}
return 0;
}
int ds_connection_stop(ds_connection_t *conn)
{
int ret = 0;
list_del(&conn->head);
if (conn->stop)
conn->stop(conn);
if (conn->dbg_free)
conn->dbg_free(conn);
if (conn->deinit)
conn->deinit(conn);
free(conn);
return ret;
}
/*cleanup in the end of conn session task*/
int ds_connection_cleanup(ds_connection_t *conn)
{
ds_inf("connection [%p] cleanup", conn);
conn->active = 0;
ds_reader_stop(conn->device, &ds_data_fn, conn);
pthread_mutex_lock(&conn->lock);
if (conn->buf) {
free(conn->buf);
conn->buf = 0;
}
pthread_mutex_unlock(&conn->lock);
ds_rb_deinit(&conn->rb);
return 0;
}
int ds_server_start(ds_server_t *server, void *arg1, void *arg2, void*(*task)(void*))
{
int ret = 0;
/*init the server inst*/
INIT_LIST_HEAD(&server->conns);
if (server->init)
ret = server->init(server, arg1, arg2);
if (ret != 0)
return -1;
server->running = 1;
ret = pthread_create(&server->thread, NULL, task, server);
if (ret != 0) {
server->running = 0;
ds_err("failed to start server due to thread failure. err(%d)", ret);
if (server->deinit)
server->deinit(server);
}
return ret;
}
int ds_server_stop(ds_server_t *server)
{
server->running = 0;
if (server->stop)
server->stop(server);
ds_inf("server stopping...");
pthread_join(server->thread, NULL);
if (server->deinit)
server->deinit(server);
ds_inf("server stopped.");
return 0;
}
int ds_server_cleanup_connections(ds_server_t *server, int force)
{
ds_connection_t *conn, *conn_tmp;
list_for_each_entry_safe(conn, conn_tmp, &server->conns, head) {
if (!force && conn->active)
continue;
ds_connection_stop(conn);
}
return 0;
}