398 lines
8.8 KiB
C
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;
|
||
|
|
}
|
||
|
|
|