417 lines
9.6 KiB
C
417 lines
9.6 KiB
C
#include "system/spinlock.h"
|
||
#include "os/os_api.h"
|
||
#include "server/rt_stream_pkg.h"
|
||
#include "lwip.h"
|
||
#include "server/net2video.h"
|
||
#include "os/os_api.h"
|
||
#include "sys_common.h"
|
||
#include "sock_api/sock_api.h"
|
||
#include "stream_core.h"
|
||
#include "app_config.h"
|
||
|
||
|
||
#define H264_CLANNEL 10000
|
||
#define JPEG_CLANNEL 10001
|
||
#define CMD_CLANNEL 10002
|
||
|
||
extern int atoi(const char *__nptr);
|
||
struct cli_info {
|
||
struct list_head entry;
|
||
void *fd;
|
||
struct sockaddr_in addr;
|
||
int id;
|
||
};
|
||
|
||
|
||
struct video_rt_tcp_server_info {
|
||
struct list_head cli_head;
|
||
struct sockaddr_in local_addr;
|
||
void *fd;
|
||
int inited;
|
||
int (*callback)(int cmd, char *buffer, int len, void *priv);
|
||
OS_SEM sem;
|
||
u32 flag;
|
||
};
|
||
|
||
|
||
|
||
|
||
static struct video_rt_tcp_server_info server_info = {
|
||
.cli_head = {
|
||
.next = &server_info.cli_head,
|
||
.prev = &server_info.cli_head,
|
||
},
|
||
};
|
||
|
||
static struct cli_info *get_tcp_net_info(u16 port);
|
||
|
||
static int path_analyze(struct rt_stream_info *info, const *path)
|
||
{
|
||
|
||
char *tmp = NULL;
|
||
char *tmp2 = NULL;
|
||
char ip[15] = {0};
|
||
u16 port = 0;
|
||
tmp = strstr(path, "cty://");
|
||
if (!tmp) {
|
||
return -1;
|
||
}
|
||
|
||
tmp += strlen("cty://");
|
||
|
||
tmp2 = strchr(tmp, ':');
|
||
printf("tmp=%s len=%d\n", tmp, tmp2 - tmp);
|
||
strncpy(ip, tmp, tmp2 - tmp);
|
||
port = atoi(tmp2 + 1);
|
||
|
||
printf("remote ip:%s port:%d\n", ip, port);
|
||
|
||
|
||
info->addr.sin_family = AF_INET;
|
||
info->addr.sin_addr.s_addr = inet_addr(ip);
|
||
info->addr.sin_port = htons(port);
|
||
return 0;
|
||
|
||
}
|
||
|
||
|
||
static void *video_rt_tcp_init(const char *path, const char *mode)
|
||
{
|
||
int ret = 0;
|
||
u16 port = 0;
|
||
log_i("video_rt_tcp_init222\n");
|
||
struct rt_stream_info *__dump = calloc(1, sizeof(struct rt_stream_info));
|
||
|
||
if (__dump == NULL) {
|
||
log_e("%s malloc fail\n", __FILE__);
|
||
return NULL;
|
||
}
|
||
|
||
|
||
path_analyze(__dump, path);
|
||
|
||
struct cli_info *info = get_tcp_net_info(ntohs(__dump->addr.sin_port));
|
||
|
||
|
||
if (info == NULL) {
|
||
log_e("%s get_tcp_net_info\n", __FILE__);
|
||
free(__dump);
|
||
return NULL;
|
||
}
|
||
|
||
memcpy((void *)&__dump->addr, (void *)&info->addr, sizeof(struct sockaddr));
|
||
__dump->fd = info->fd;
|
||
|
||
return (void *)__dump;
|
||
}
|
||
static int video_rt_tcp_send(void *file, void *buf, u32 len, u8 type)
|
||
{
|
||
struct rt_stream_info *__dump = (struct rt_stream_info *)file;
|
||
int ret = 0;
|
||
u32 data_size = len;
|
||
if (type == H264_TYPE_VIDEO || type == JPEG_TYPE_VIDEO) {
|
||
data_size |= (1 << 31);
|
||
} else if (type == PCM_TYPE_AUDIO) {
|
||
data_size &= ~(1 << 31);
|
||
}
|
||
|
||
ret = sock_send(__dump->fd, (char *)&data_size, 4, 0);
|
||
if (ret <= 0) {
|
||
return ret;
|
||
}
|
||
ret = sock_send(__dump->fd, buf, len, 0);
|
||
|
||
return ret;
|
||
|
||
}
|
||
|
||
static int video_rt_tcp_uninit(void *file)
|
||
{
|
||
log_i("video_rt_tcp_uninit2222\n\n\n\n\n\n");
|
||
int ret = 0;
|
||
struct rt_stream_info *__dump = (struct rt_stream_info *)file;
|
||
u32 end_frame = 0x12348765;
|
||
ret = sock_send(__dump->fd, (char *)&end_frame, 4, 0);
|
||
if (ret <= 0) {
|
||
return -1;
|
||
}
|
||
free(__dump);
|
||
return 0;
|
||
}
|
||
REGISTER_NET_VIDEO_STREAM_SUDDEV(tcp2_video_stream_sub) = {
|
||
.name = "cty",
|
||
.open = video_rt_tcp_init,
|
||
.write = video_rt_tcp_send,
|
||
.close = video_rt_tcp_uninit,
|
||
};
|
||
|
||
|
||
|
||
struct cli_info *get_tcp_net_info(u16 port)
|
||
{
|
||
struct list_head *pos = NULL;
|
||
struct cli_info *cli = NULL;
|
||
int count = 0;
|
||
list_for_each(pos, &server_info.cli_head) {
|
||
cli = list_entry(pos, struct cli_info, entry);
|
||
if (port == cli->id) {
|
||
log_i("get id:%d ip:%s port:%d\n\n", cli->id, inet_ntoa(cli->addr.sin_addr.s_addr), htons(cli->addr.sin_port));
|
||
/* sock_clr_quit(cli->fd); */
|
||
return cli;
|
||
}
|
||
|
||
}
|
||
|
||
log_w("not find cli info \n");
|
||
return cli;
|
||
|
||
}
|
||
|
||
/*
|
||
*命令格式
|
||
*|len|cmd|data|
|
||
*|4byte|4byte|Nbyte|
|
||
*cmd:命令号
|
||
*len:总长度
|
||
*data:数据(主要是给start_app传给启动video4的参数)
|
||
* */
|
||
|
||
static u8 buffer[1024];
|
||
static void cmd_cli_task(void *arg)
|
||
{
|
||
struct list_head *pos = NULL;
|
||
struct cli_info *cli = NULL;
|
||
int ret = 0;
|
||
int len = 0;
|
||
int cmd = 0;
|
||
int find = 0;
|
||
// 查找是否已经存在
|
||
list_for_each(pos, &server_info.cli_head) {
|
||
cli = list_entry(pos, struct cli_info, entry);
|
||
if (CMD_CLANNEL == cli->id) {
|
||
find = 1;
|
||
break;
|
||
}
|
||
}
|
||
if (!find) {
|
||
return;
|
||
}
|
||
|
||
log_d("find it ip:%s port:%d\n\n", inet_ntoa(cli->addr.sin_addr.s_addr), htons(cli->addr.sin_port));
|
||
|
||
while (1) {
|
||
//总长度
|
||
ret = sock_recv(cli->fd, (char *)&len, 4, 0);
|
||
if (ret != 4) {
|
||
log_e("sock_recv fail1\n");
|
||
goto exit_;
|
||
}
|
||
log_i("len=%d\n", len);
|
||
//命令号
|
||
ret = sock_recv(cli->fd, (char *)&cmd, 4, 0);
|
||
if (ret != 4) {
|
||
log_e("sock_recv fail2\n");
|
||
goto exit_;
|
||
}
|
||
log_i("cmd=%d\n", cmd);
|
||
//数据
|
||
//
|
||
memset(buffer, 0, sizeof(buffer));
|
||
if (len - 4 != 0) {
|
||
ret = sock_recv(cli->fd, buffer, len - 4, 0);
|
||
if (ret < 0) {
|
||
log_e("sock_recv fail4\n");
|
||
goto exit_;
|
||
}
|
||
}
|
||
if (server_info.callback) {
|
||
ret = server_info.callback(cmd, buffer, len - 4, NULL);
|
||
}
|
||
if (ret != CMD_NO_ERR) {
|
||
log_e("cmd err=%d\n", ret);
|
||
}
|
||
|
||
}
|
||
|
||
exit_:
|
||
log_d("cmd_cli_task exit\n");
|
||
|
||
}
|
||
|
||
|
||
int cmd_send(struct cmd_ctl *cinfo)
|
||
{
|
||
struct list_head *pos = NULL;
|
||
struct cli_info *cli = NULL;
|
||
int ret = 0;
|
||
int len = 0;
|
||
|
||
// 查找是否已经存在
|
||
list_for_each(pos, &server_info.cli_head) {
|
||
cli = list_entry(pos, struct cli_info, entry);
|
||
if (CMD_CLANNEL == cli->id) {
|
||
break;
|
||
}
|
||
}
|
||
log_i("send0\n");
|
||
ret = sock_send(cli->fd, (char *)cinfo, 8, 0);
|
||
if (ret != 8) {
|
||
log_e("sock send fail1111\n");
|
||
return -1;
|
||
}
|
||
|
||
log_i("send1 len=%d\n", cinfo->len - 4);
|
||
if (cinfo->len - 4 != 0) {
|
||
ret = sock_send(cli->fd, cinfo->data, cinfo->len - 4, 0);
|
||
if (ret != cinfo->len - 4) {
|
||
log_e("sock send fail22222 ret=%d\n", ret);
|
||
return -1;
|
||
}
|
||
}
|
||
log_i("send2\n");
|
||
return 0;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
static void __do_sock_accpet(void *arg)
|
||
{
|
||
u32 find = 0;
|
||
struct list_head *pos = NULL;
|
||
struct cli_info *cli = NULL;
|
||
int ret = 0;
|
||
u8 task_name[64];
|
||
u32 count = 0;
|
||
|
||
socklen_t len = sizeof(server_info.local_addr);
|
||
while (1) {
|
||
|
||
struct cli_info *__cli = calloc(1, sizeof(sizeof(struct cli_info)));
|
||
if (__cli == NULL) {
|
||
log_e("malloc fail\n");
|
||
while (1);
|
||
}
|
||
|
||
|
||
__cli->fd = sock_accept(server_info.fd, (struct sockaddr *)&__cli->addr, &len, NULL, NULL);
|
||
if (__cli->fd == NULL) {
|
||
log_w("some error in here\n\n");
|
||
free(__cli);
|
||
continue;
|
||
}
|
||
if (server_info.flag) {
|
||
free(__cli);
|
||
break;
|
||
}
|
||
|
||
ret = sock_recv(__cli->fd, (char *)&__cli->id, 4, 0);
|
||
if (ret != 4) {
|
||
sock_unreg(__cli->fd);
|
||
free(__cli->fd);
|
||
continue;
|
||
}
|
||
log_i("__cli->id = %d\n", __cli->id);
|
||
|
||
list_add_tail(&__cli->entry, &server_info.cli_head);
|
||
|
||
//命令通道,另开线程处理
|
||
if (__cli->id == CMD_CLANNEL) {
|
||
sprintf(task_name, "cmd_cli_task%x", count++);
|
||
ret = thread_fork(task_name, 28, 0x1000, 0, 0, cmd_cli_task, NULL);
|
||
if (ret != OS_NO_ERR) {
|
||
log_e("thread_fork fail\n");
|
||
continue;
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
int video_rt_tcp_server_init2(int port, int (*callback)(int, char *, int, void *))
|
||
{
|
||
int ret = 0;
|
||
log_i("video_rt_tcp_server_init2\n");
|
||
|
||
memset(&server_info, 0x0, sizeof(server_info));
|
||
os_sem_create(&server_info.sem, 0);
|
||
|
||
server_info.local_addr.sin_family = AF_INET;
|
||
server_info.local_addr.sin_addr.s_addr = htonl(INADDR_ANY) ;
|
||
server_info.local_addr.sin_port = htons(port);
|
||
|
||
|
||
server_info.fd = sock_reg(AF_INET, SOCK_STREAM, 0, NULL, NULL);
|
||
|
||
if (server_info.fd == NULL) {
|
||
return -1;
|
||
}
|
||
|
||
u32 opt = 1;
|
||
if (sock_setsockopt(server_info.fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
||
log_e("%s sock_bind fail\n", __FILE__);
|
||
return -1;
|
||
}
|
||
|
||
|
||
if (sock_bind(server_info.fd, (struct sockaddr *)&server_info.local_addr, sizeof(struct sockaddr))) {
|
||
log_e("%s sock_bind fail\n", __FILE__);
|
||
return -1;
|
||
}
|
||
sock_listen(server_info.fd, 0x5);
|
||
|
||
INIT_LIST_HEAD(&server_info.cli_head);
|
||
server_info.inited = 1;
|
||
server_info.callback = callback;
|
||
|
||
ret = thread_fork("__do_sock_accpet", 28, 0x1000, 0, 0, __do_sock_accpet, NULL);
|
||
if (ret != OS_NO_ERR) {
|
||
log_e("%s thread fork fail\n", __FILE__);
|
||
return -1;
|
||
|
||
}
|
||
|
||
return 0;
|
||
|
||
}
|
||
void video_rt_tcp_server_uninit2()
|
||
{
|
||
printf("video_rt_tcp_server_uninit\n");
|
||
server_info.flag = 1;
|
||
sock_set_quit(server_info.fd);
|
||
sock_unreg(server_info.fd);
|
||
server_info.flag = 0;
|
||
// 断开所有客户端和删除链表
|
||
}
|
||
|
||
void video_disconnect_all_cli()
|
||
{
|
||
struct list_head *pos = NULL, *n = NULL;
|
||
struct cli_info *cf = NULL;
|
||
if (!server_info.inited) {
|
||
return;
|
||
}
|
||
log_d("disconnect all client\n");
|
||
list_for_each_safe(pos, n, &server_info.cli_head) {
|
||
cf = list_entry(pos, struct cli_info, entry);
|
||
list_del(&cf->entry);
|
||
if (cf->fd != NULL) {
|
||
sock_unreg(cf->fd);
|
||
cf->fd = NULL;
|
||
}
|
||
if (cf != NULL) {
|
||
free(cf);
|
||
cf = NULL;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|