327 lines
11 KiB
C
327 lines
11 KiB
C
|
|
#include "basic_include.h"
|
||
|
|
#include "lwip/sockets.h"
|
||
|
|
#include "netif/ethernetif.h"
|
||
|
|
#include "lib/net/eloop/eloop.h"
|
||
|
|
#include "syscfg.h"
|
||
|
|
#include "walkie_talkie_calling.h"
|
||
|
|
|
||
|
|
#define CALLING_TIMEOUT 100
|
||
|
|
#define WAITACCEPT_TIMEOUT 20
|
||
|
|
#define WAITCONNECT_TIMEOUT 300
|
||
|
|
|
||
|
|
typedef void (*walkie_talkie_calling_cb)(uint32 local_status);
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
struct os_msgqueue recv_msgq;
|
||
|
|
struct os_msgqueue user_msgq;
|
||
|
|
struct os_mutex mutex;
|
||
|
|
walkie_talkie_calling_cb cb_func;
|
||
|
|
void *task_hdl;
|
||
|
|
struct sockaddr_in remote_addr;
|
||
|
|
uint8 start;
|
||
|
|
uint32 remote_status;
|
||
|
|
uint32 local_status;
|
||
|
|
uint32 user_status;
|
||
|
|
uint32 recv_info;
|
||
|
|
uint32 send_info;
|
||
|
|
uint32 cur_seq;
|
||
|
|
int32 heartbeat_fd;
|
||
|
|
uint32 timeout_cnt;
|
||
|
|
uint32 timeout;
|
||
|
|
} CALLING_STRUCT;
|
||
|
|
|
||
|
|
CALLING_STRUCT calling_s;
|
||
|
|
|
||
|
|
void walkie_talkie_heartbeat_recv(void *d)
|
||
|
|
{
|
||
|
|
int32 read_len = 0;
|
||
|
|
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||
|
|
uint32 recv_info = 0;
|
||
|
|
|
||
|
|
while(1) {
|
||
|
|
recv_info = 0;
|
||
|
|
read_len = recvfrom(calling_s.heartbeat_fd, &recv_info, 4, 0, (struct sockaddr*)&(calling_s.remote_addr), (socklen_t*)&addrlen);
|
||
|
|
os_mutex_lock(&calling_s.mutex, osWaitForever);
|
||
|
|
if((read_len <= 0 && calling_s.local_status != status_none) || ((recv_info & 0xFFFF) == 0) ||
|
||
|
|
(calling_s.cur_seq && ((recv_info & 0xFFFF) != calling_s.cur_seq))) {
|
||
|
|
calling_s.timeout_cnt++;
|
||
|
|
if(calling_s.local_status == wait_connect || calling_s.local_status == status_none) {
|
||
|
|
calling_s.timeout = WAITCONNECT_TIMEOUT;
|
||
|
|
}
|
||
|
|
else if(calling_s.local_status == wait_accept_connect) {
|
||
|
|
calling_s.timeout = WAITACCEPT_TIMEOUT;
|
||
|
|
}
|
||
|
|
if(calling_s.timeout_cnt >= calling_s.timeout) {
|
||
|
|
calling_s.timeout_cnt = calling_s.timeout;
|
||
|
|
calling_s.remote_status = disconnecting;
|
||
|
|
}
|
||
|
|
os_mutex_unlock(&calling_s.mutex);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
os_mutex_unlock(&calling_s.mutex);
|
||
|
|
if(read_len > 0) {
|
||
|
|
calling_s.timeout_cnt = 0;
|
||
|
|
calling_s.remote_status = connecting;
|
||
|
|
if(calling_s.recv_info != recv_info) {
|
||
|
|
calling_s.recv_info = recv_info;
|
||
|
|
os_msgq_put(&calling_s.recv_msgq, calling_s.recv_info, osWaitForever);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void walkie_talkie_calling_thread(void *d)
|
||
|
|
{
|
||
|
|
int32 err = -1;
|
||
|
|
int32 time_out = 100;
|
||
|
|
int32 recv_msgq_ret = RET_ERR;
|
||
|
|
int32 user_msgq_ret = RET_ERR;
|
||
|
|
uint32 recv_info = 0;
|
||
|
|
uint32 recv_status = status_none;
|
||
|
|
uint32 user_ctrl = calling_none;
|
||
|
|
uint32 ipaddr = 0;
|
||
|
|
struct sockaddr_in remote_addr;
|
||
|
|
struct sockaddr_in local_addr;
|
||
|
|
socklen_t addrlen = sizeof(struct sockaddr_in);
|
||
|
|
|
||
|
|
if(sys_cfgs.wifi_mode == WIFI_MODE_STA) {
|
||
|
|
do{
|
||
|
|
if(sys_cfgs.wifi_mode == WIFI_MODE_AP)
|
||
|
|
break;
|
||
|
|
ipaddr = lwip_netif_get_ip2("w0").addr;
|
||
|
|
os_sleep_ms(100);
|
||
|
|
}while((ipaddr&0xff000000) == 0x1000000);
|
||
|
|
}
|
||
|
|
calling_s.heartbeat_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||
|
|
if(calling_s.heartbeat_fd < 0) {
|
||
|
|
goto walkie_talkie_calling_thread_exit;
|
||
|
|
}
|
||
|
|
local_addr.sin_family = AF_INET;
|
||
|
|
local_addr.sin_port = htons(5010);
|
||
|
|
local_addr.sin_addr.s_addr = 0;
|
||
|
|
err = bind(calling_s.heartbeat_fd, (struct sockaddr*)&local_addr, addrlen);
|
||
|
|
if(err == -1) {
|
||
|
|
goto walkie_talkie_calling_thread_exit;
|
||
|
|
}
|
||
|
|
setsockopt(calling_s.heartbeat_fd, SOL_SOCKET, SO_RCVTIMEO, &time_out, sizeof(int32_t));
|
||
|
|
remote_addr.sin_family = AF_INET;
|
||
|
|
remote_addr.sin_port = htons(5010);
|
||
|
|
if(sys_cfgs.wifi_mode == WIFI_MODE_STA) {
|
||
|
|
remote_addr.sin_addr.s_addr = inet_addr("192.168.169.1");
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
remote_addr.sin_addr.s_addr = inet_addr("192.168.169.100");
|
||
|
|
}
|
||
|
|
os_task_create("walkie_talkie_heartbeat_recv", walkie_talkie_heartbeat_recv, NULL, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
||
|
|
calling_s.start = 1;
|
||
|
|
while(1) {
|
||
|
|
if(os_memcmp(&calling_s.remote_addr.sin_addr, &remote_addr.sin_addr, sizeof(struct in_addr))) {
|
||
|
|
os_memcpy(&calling_s.remote_addr.sin_addr, &remote_addr.sin_addr, sizeof(struct in_addr));
|
||
|
|
}
|
||
|
|
recv_info = 0;
|
||
|
|
user_ctrl = calling_none;
|
||
|
|
recv_status = status_none;
|
||
|
|
recv_info = os_msgq_get2(&calling_s.recv_msgq, 1, &recv_msgq_ret);
|
||
|
|
user_ctrl = os_msgq_get2(&calling_s.user_msgq, 1, &user_msgq_ret);
|
||
|
|
if(recv_msgq_ret == RET_OK) {
|
||
|
|
recv_status = recv_info >> 16;
|
||
|
|
// os_printf("\n\n****recv_status:%d %d****\n\n",recv_status,calling_s.local_status);
|
||
|
|
}
|
||
|
|
os_mutex_lock(&calling_s.mutex, osWaitForever);
|
||
|
|
switch(calling_s.local_status) {
|
||
|
|
case status_none:
|
||
|
|
{
|
||
|
|
if(recv_status == wait_connect) {
|
||
|
|
calling_s.local_status = wait_accept_connect;
|
||
|
|
calling_s.user_status = wait_accept_connect;
|
||
|
|
calling_s.cur_seq = (recv_info & 0xFFFF);
|
||
|
|
}
|
||
|
|
else if(user_ctrl == calling_start) {
|
||
|
|
calling_s.local_status = wait_connect;
|
||
|
|
calling_s.timeout_cnt = 0;
|
||
|
|
calling_s.remote_status = connecting;
|
||
|
|
os_random_bytes((uint8_t*)(&calling_s.cur_seq), 4);
|
||
|
|
calling_s.cur_seq &= 0xFFFF;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case wait_connect:
|
||
|
|
{
|
||
|
|
if(recv_status == wait_disconnect) {
|
||
|
|
calling_s.local_status = disconnecting;
|
||
|
|
}
|
||
|
|
else if(user_ctrl == calling_stop) {
|
||
|
|
calling_s.local_status = wait_disconnect;
|
||
|
|
}
|
||
|
|
else if(recv_status == accept_connect) {
|
||
|
|
calling_s.local_status = connecting;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case wait_accept_connect:
|
||
|
|
{
|
||
|
|
if(recv_status == wait_disconnect) {
|
||
|
|
calling_s.local_status = disconnecting;
|
||
|
|
}
|
||
|
|
else if(user_ctrl == calling_start) {
|
||
|
|
calling_s.local_status = accept_connect;
|
||
|
|
calling_s.user_status = accept_connect;
|
||
|
|
}
|
||
|
|
else if(user_ctrl == calling_stop) {
|
||
|
|
calling_s.local_status = wait_disconnect;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case accept_connect:
|
||
|
|
{
|
||
|
|
if(recv_status == wait_disconnect) {
|
||
|
|
calling_s.local_status = disconnecting;
|
||
|
|
}
|
||
|
|
else if(user_ctrl == calling_stop) {
|
||
|
|
calling_s.local_status = wait_disconnect;
|
||
|
|
}
|
||
|
|
else if(recv_status == connecting) {
|
||
|
|
calling_s.local_status = connecting;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case connecting:
|
||
|
|
{
|
||
|
|
if(recv_status == wait_disconnect) {
|
||
|
|
calling_s.local_status = disconnecting;
|
||
|
|
}
|
||
|
|
else if(user_ctrl == calling_stop) {
|
||
|
|
calling_s.local_status = wait_disconnect;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
calling_s.user_status = connecting;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case wait_disconnect:
|
||
|
|
{
|
||
|
|
if(user_ctrl == calling_start) {
|
||
|
|
calling_s.local_status = wait_connect;
|
||
|
|
calling_s.timeout_cnt = 0;
|
||
|
|
calling_s.remote_status = connecting;
|
||
|
|
os_random_bytes((uint8_t*)(&calling_s.cur_seq), 4);
|
||
|
|
calling_s.cur_seq &= 0xFFFF;
|
||
|
|
}
|
||
|
|
else if(recv_status == disconnecting) {
|
||
|
|
calling_s.local_status = disconnecting;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case disconnecting:
|
||
|
|
{
|
||
|
|
if(recv_status == wait_connect) {
|
||
|
|
calling_s.local_status = wait_accept_connect;
|
||
|
|
calling_s.user_status = wait_accept_connect;
|
||
|
|
calling_s.cur_seq = (recv_info & 0xFFFF);
|
||
|
|
}
|
||
|
|
else if(user_ctrl == calling_start) {
|
||
|
|
calling_s.local_status = wait_connect;
|
||
|
|
calling_s.timeout_cnt = 0;
|
||
|
|
calling_s.remote_status = connecting;
|
||
|
|
os_random_bytes((uint8_t*)(&calling_s.cur_seq), 4);
|
||
|
|
calling_s.cur_seq &= 0xFFFF;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if(calling_s.remote_status == disconnecting) {
|
||
|
|
calling_s.user_status = disconnecting;
|
||
|
|
calling_s.cur_seq = 0;
|
||
|
|
calling_s.local_status = status_none;
|
||
|
|
}
|
||
|
|
else if(calling_s.local_status == disconnecting) {
|
||
|
|
calling_s.user_status = disconnecting;
|
||
|
|
calling_s.cur_seq = 0;
|
||
|
|
}
|
||
|
|
else if(calling_s.local_status == wait_disconnect) {
|
||
|
|
calling_s.user_status = disconnecting;
|
||
|
|
}
|
||
|
|
os_mutex_unlock(&calling_s.mutex);
|
||
|
|
if(calling_s.local_status != wait_accept_connect) {
|
||
|
|
calling_s.send_info = calling_s.cur_seq | (calling_s.local_status << 16);
|
||
|
|
sendto(calling_s.heartbeat_fd, &calling_s.send_info, 4, 0, (struct sockaddr*)&remote_addr, addrlen);
|
||
|
|
}
|
||
|
|
calling_s.cb_func(calling_s.local_status);
|
||
|
|
if(recv_msgq_ret & user_msgq_ret) {
|
||
|
|
os_sleep_ms(100);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
walkie_talkie_calling_thread_exit:
|
||
|
|
if(calling_s.heartbeat_fd >= 0) {
|
||
|
|
close(calling_s.heartbeat_fd);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int32 walkie_talkie_calling_init(void *cb_func)
|
||
|
|
{
|
||
|
|
calling_s.heartbeat_fd = -1;
|
||
|
|
if(os_msgq_init(&calling_s.recv_msgq, 1) != RET_OK) {
|
||
|
|
goto walkie_talkie_calling_init_fail;
|
||
|
|
}
|
||
|
|
if(os_msgq_init(&calling_s.user_msgq, 1) != RET_OK) {
|
||
|
|
goto walkie_talkie_calling_init_fail;
|
||
|
|
}
|
||
|
|
if(os_mutex_init(&calling_s.mutex) != RET_OK) {
|
||
|
|
goto walkie_talkie_calling_init_fail;
|
||
|
|
}
|
||
|
|
calling_s.user_status = disconnecting;
|
||
|
|
calling_s.cb_func = cb_func;
|
||
|
|
calling_s.task_hdl = os_task_create("walkie_talkie_calling_thread", walkie_talkie_calling_thread, NULL, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
|
||
|
|
if(calling_s.task_hdl == NULL) {
|
||
|
|
goto walkie_talkie_calling_init_fail;
|
||
|
|
}
|
||
|
|
return RET_OK;
|
||
|
|
walkie_talkie_calling_init_fail:
|
||
|
|
os_printf("walkie_talkie_calling_init fail\n");
|
||
|
|
if(calling_s.recv_msgq.hdl) {
|
||
|
|
os_msgq_del(&calling_s.recv_msgq);
|
||
|
|
}
|
||
|
|
if(calling_s.user_msgq.hdl) {
|
||
|
|
os_msgq_del(&calling_s.user_msgq);
|
||
|
|
}
|
||
|
|
if(calling_s.mutex.hdl) {
|
||
|
|
os_mutex_del(&calling_s.mutex);
|
||
|
|
}
|
||
|
|
return RET_ERR;
|
||
|
|
}
|
||
|
|
|
||
|
|
int32 walkie_talkie_calling_set(uint32 ctrl)
|
||
|
|
{
|
||
|
|
if(calling_s.user_msgq.hdl == NULL) {
|
||
|
|
return RET_ERR;
|
||
|
|
}
|
||
|
|
os_mutex_lock(&calling_s.mutex, osWaitForever);
|
||
|
|
if(calling_s.start == 0) {
|
||
|
|
os_mutex_unlock(&calling_s.mutex);
|
||
|
|
return RET_ERR;
|
||
|
|
}
|
||
|
|
if(ctrl == calling_stop) {
|
||
|
|
if(calling_s.user_status == status_none || calling_s.user_status == wait_disconnect || calling_s.user_status == disconnecting) {
|
||
|
|
os_mutex_unlock(&calling_s.mutex);
|
||
|
|
return RET_ERR;
|
||
|
|
}
|
||
|
|
calling_s.user_status = wait_disconnect;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if(calling_s.user_status == wait_connect || calling_s.user_status == accept_connect || calling_s.user_status == connecting) {
|
||
|
|
os_mutex_unlock(&calling_s.mutex);
|
||
|
|
return RET_ERR;
|
||
|
|
}
|
||
|
|
calling_s.user_status = wait_connect;
|
||
|
|
}
|
||
|
|
os_mutex_unlock(&calling_s.mutex);
|
||
|
|
os_msgq_put(&calling_s.user_msgq, ctrl, osWaitForever);
|
||
|
|
return RET_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
int32 walkie_talkie_calling_get(void)
|
||
|
|
{
|
||
|
|
return calling_s.user_status;
|
||
|
|
}
|