404 lines
11 KiB
C
404 lines
11 KiB
C
/**
|
|
* @file wm_udp_demo.c
|
|
*
|
|
* @brief udp demo
|
|
*
|
|
* @author dave
|
|
*
|
|
* Copyright (c) 2016 Winner Microelectronics Co., Ltd.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "wm_include.h"
|
|
#include "wm_demo.h"
|
|
#include "wm_sockets.h"
|
|
|
|
#if DEMO_UDP
|
|
#define DEMO_UDP_BROADCAST 0
|
|
#define DEMO_UDP_UNICAST 1
|
|
#define DEMO_UDP_MUTICAST 2
|
|
|
|
#define DEMO_UDP_TASK_SIZE 512
|
|
#define DEMO_UDP_BUF_SIZE 1024
|
|
|
|
#define DEMO_UDP_LOCAL_PORT 3000
|
|
|
|
static u8 MCASTIP[4] = {224, 1, 2, 1};
|
|
|
|
static OS_STK udp_task_stk[DEMO_UDP_TASK_SIZE];
|
|
static OS_STK udp_rcv_task_stk[DEMO_UDP_TASK_SIZE];
|
|
|
|
|
|
/**
|
|
* @typedef struct demo_udp
|
|
*/
|
|
typedef struct demo_udp
|
|
{
|
|
tls_os_queue_t *udp_q;
|
|
struct ip_mreq mreq;
|
|
char *sock_rx;
|
|
char *sock_tx;
|
|
int cast_mode;
|
|
bool socket_ok;
|
|
int socket_num;
|
|
int port;
|
|
u32 ip_addr;
|
|
u32 rcv_data_len;
|
|
int snd_skt_no;
|
|
int snd_data_len;
|
|
|
|
} ST_Demo_Udp;
|
|
|
|
ST_Demo_Udp *demo_udp = NULL;
|
|
|
|
static void demo_udp_task(void *sdata);
|
|
|
|
|
|
int create_udp_socket_demo(void)
|
|
{
|
|
struct sockaddr_in pin;
|
|
struct tls_ethif *ethif;
|
|
int ttl = 10;
|
|
int loop = 0;
|
|
|
|
ethif = tls_netif_get_ethif();
|
|
printf("local ip : %d.%d.%d.%d\n", ip4_addr1(ip_2_ip4(ðif->ip_addr)), ip4_addr2(ip_2_ip4(ðif->ip_addr)),
|
|
|
|
ip4_addr3(ip_2_ip4(ðif->ip_addr)), ip4_addr4(ip_2_ip4(ðif->ip_addr)));
|
|
demo_udp->socket_num = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
|
|
|
memset(&pin, 0, sizeof(struct sockaddr_in));
|
|
pin.sin_family = AF_INET;
|
|
pin.sin_addr.s_addr = (u32)0x00000000UL; //IPADDR_ANY
|
|
pin.sin_port = htons(DEMO_UDP_LOCAL_PORT);
|
|
|
|
printf("local port :%d\n", DEMO_UDP_LOCAL_PORT);
|
|
if (bind(demo_udp->socket_num, (struct sockaddr *) &pin, sizeof(pin)) == -1)
|
|
{
|
|
printf("bind err\n");
|
|
closesocket(demo_udp->socket_num);
|
|
return WM_FAILED;
|
|
}
|
|
|
|
if (DEMO_UDP_MUTICAST == demo_udp->cast_mode)
|
|
{
|
|
//Configure multicast TTL
|
|
printf("set muticast\n");
|
|
if (setsockopt(demo_udp->socket_num, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
|
|
{
|
|
printf("IP_MULTICAST_TTL");
|
|
closesocket(demo_udp->socket_num);
|
|
return WM_FAILED;
|
|
}
|
|
//Local Loop setting
|
|
if (setsockopt(demo_udp->socket_num, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0)
|
|
{
|
|
printf("IP_MULTICAST_LOOP");
|
|
closesocket(demo_udp->socket_num);
|
|
return WM_FAILED;
|
|
}
|
|
MEMCPY((char *) & (demo_udp->mreq.imr_multiaddr.s_addr), (char *)MCASTIP, 4);
|
|
demo_udp->mreq.imr_interface.s_addr = htonl(0x00000000UL);
|
|
//join muticast group
|
|
if (setsockopt(demo_udp->socket_num, IPPROTO_IP, IP_ADD_MEMBERSHIP, &(demo_udp->mreq), sizeof(demo_udp->mreq)) < 0)
|
|
{
|
|
printf("IP_ADD_MEMBERSHIP");
|
|
closesocket(demo_udp->socket_num);
|
|
return WM_FAILED;
|
|
}
|
|
}
|
|
|
|
demo_udp->socket_ok = TRUE;
|
|
return WM_SUCCESS;
|
|
}
|
|
|
|
|
|
static void demo_udp_recv_task(void *sdata)
|
|
{
|
|
ST_Demo_Udp *udp = (ST_Demo_Udp *)sdata;
|
|
int ret = 0;
|
|
struct sockaddr_in pin;
|
|
socklen_t addrlen = sizeof(struct sockaddr);
|
|
|
|
for(;;)
|
|
{
|
|
if (udp->socket_ok)
|
|
{
|
|
ret = recvfrom(udp->socket_num, udp->sock_rx, DEMO_UDP_BUF_SIZE,
|
|
0, (struct sockaddr *)&pin, &addrlen);
|
|
|
|
if (ret > 0)
|
|
{
|
|
printf("rcv from %s : port : %d len = %d\n", inet_ntoa(pin.sin_addr), htons(pin.sin_port), ret);
|
|
}
|
|
else
|
|
{
|
|
printf("rcv err\n");
|
|
udp->socket_ok = FALSE;
|
|
if (DEMO_UDP_MUTICAST == udp->cast_mode)
|
|
{
|
|
setsockopt(udp->socket_num, IPPROTO_IP, IP_DROP_MEMBERSHIP, &(udp->mreq), sizeof(udp->mreq));
|
|
}
|
|
closesocket(udp->socket_num);
|
|
printf("closesocket\n");
|
|
tls_os_queue_send(udp->udp_q, (void *)DEMO_MSG_SOCKET_ERR, 0);
|
|
}
|
|
continue;
|
|
}
|
|
tls_os_time_delay(10);
|
|
}
|
|
}
|
|
|
|
int udp_send_data_demo(int len)
|
|
{
|
|
printf("\nlen=%d\n", len);
|
|
if (NULL == demo_udp)
|
|
{
|
|
return WM_FAILED;
|
|
}
|
|
if (!demo_udp->socket_ok)
|
|
{
|
|
printf("skt not created\n");
|
|
return WM_FAILED;
|
|
}
|
|
|
|
demo_udp->snd_data_len = len;
|
|
tls_os_queue_send(demo_udp->udp_q, (void *)DEMO_MSG_UART_RECEIVE_DATA, 0);
|
|
|
|
return WM_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
* @brief udp demo
|
|
*
|
|
* @param[in] cast_mode unicast or broadcast, 0 is broadcast, 1 is unicast, default is broadcast
|
|
* @param[in] port port num
|
|
* @param[in] *ip if cast mode is unicast, need define ip addr.
|
|
*
|
|
* @retval 0 success
|
|
* @retval other failed
|
|
*
|
|
* @note None
|
|
*/
|
|
int socket_udp_demo(int cast_mode, int port, char *ip)
|
|
{
|
|
if (demo_udp)
|
|
{
|
|
printf("run\n");
|
|
return WM_FAILED;
|
|
}
|
|
printf("udp demo,cast:%d, port:%d\n", cast_mode, port);
|
|
if(-1 == cast_mode)
|
|
{
|
|
cast_mode = DEMO_UDP_BROADCAST;
|
|
}
|
|
if(-1 == port || port > 65536)
|
|
{
|
|
printf("port err\n");
|
|
return WM_FAILED;
|
|
}
|
|
if(NULL == ip)
|
|
{
|
|
if (DEMO_UDP_UNICAST == cast_mode)
|
|
{
|
|
printf("donot input ip,will send broadcast packet\n");
|
|
cast_mode = DEMO_UDP_BROADCAST;
|
|
}
|
|
}
|
|
|
|
if (NULL == demo_udp)
|
|
{
|
|
demo_udp = tls_mem_alloc(sizeof(ST_Demo_Udp));
|
|
if (NULL == demo_udp)
|
|
{
|
|
goto _error;
|
|
}
|
|
memset(demo_udp, 0, sizeof(ST_Demo_Udp));
|
|
|
|
demo_udp->sock_rx = tls_mem_alloc(DEMO_UDP_BUF_SIZE + 1);
|
|
if (NULL == demo_udp->sock_rx)
|
|
{
|
|
goto _error3;
|
|
}
|
|
|
|
demo_udp->sock_tx = tls_mem_alloc(DEMO_UDP_BUF_SIZE + 1);
|
|
if (NULL == demo_udp->sock_tx)
|
|
{
|
|
goto _error4;
|
|
}
|
|
|
|
tls_os_queue_create(&(demo_udp->udp_q), DEMO_QUEUE_SIZE);
|
|
//deal with socket's message
|
|
tls_os_task_create(NULL, NULL,
|
|
demo_udp_task,
|
|
(void *)demo_udp,
|
|
(void *)udp_task_stk, /* task's stack start address */
|
|
DEMO_UDP_TASK_SIZE*sizeof(u32), /* task's stack size, unit:byte */
|
|
DEMO_UDP_TASK_PRIO,
|
|
0);
|
|
|
|
//deal with socket's rx data
|
|
tls_os_task_create(NULL, NULL,
|
|
demo_udp_recv_task,
|
|
(void *)demo_udp,
|
|
(void *)udp_rcv_task_stk, /* task's stack start address */
|
|
DEMO_UDP_TASK_SIZE*sizeof(u32), /* task's stack size, unit:byte */
|
|
DEMO_UDP_RECEIVE_TASK_PRIO,
|
|
0);
|
|
}
|
|
|
|
demo_udp->port = port;
|
|
if (ip)
|
|
{
|
|
demo_udp->ip_addr = ipaddr_addr(ip);
|
|
}
|
|
demo_udp->cast_mode = cast_mode;
|
|
|
|
return WM_SUCCESS;
|
|
|
|
_error4:
|
|
tls_mem_free(demo_udp->sock_rx);
|
|
_error3:
|
|
tls_mem_free(demo_udp);
|
|
demo_udp = NULL;
|
|
_error:
|
|
return WM_FAILED;
|
|
}
|
|
|
|
|
|
static void udp_net_status_changed_event(u8 status )
|
|
{
|
|
switch(status)
|
|
{
|
|
case NETIF_WIFI_JOIN_FAILED:
|
|
tls_os_queue_send(demo_udp->udp_q, (void *)DEMO_MSG_WJOIN_FAILD, 0);
|
|
break;
|
|
case NETIF_WIFI_JOIN_SUCCESS:
|
|
tls_os_queue_send(demo_udp->udp_q, (void *)DEMO_MSG_WJOIN_SUCCESS, 0);
|
|
break;
|
|
case NETIF_IP_NET_UP:
|
|
tls_os_queue_send(demo_udp->udp_q, (void *)DEMO_MSG_SOCKET_CREATE, 0);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void demo_udp_task(void *sdata)
|
|
{
|
|
ST_Demo_Udp *udp = (ST_Demo_Udp *)sdata;
|
|
void *msg;
|
|
struct tls_ethif *ethif = tls_netif_get_ethif();
|
|
int len;
|
|
int ret;
|
|
struct sockaddr_in pin;
|
|
|
|
if(ethif->status) /*connected to ap and get IP*/
|
|
{
|
|
tls_os_queue_send(udp->udp_q, (void *)DEMO_MSG_SOCKET_CREATE, 0);
|
|
}
|
|
else
|
|
{
|
|
struct tls_param_ip ip_param;
|
|
|
|
tls_param_get(TLS_PARAM_ID_IP, &ip_param, TRUE);
|
|
ip_param.dhcp_enable = TRUE;
|
|
tls_param_set(TLS_PARAM_ID_IP, &ip_param, TRUE);
|
|
tls_wifi_set_oneshot_flag(1); /*Enable oneshot configuration*/
|
|
printf("\nwait one shot......\n");
|
|
}
|
|
tls_netif_add_status_event(udp_net_status_changed_event);
|
|
|
|
memset(&pin, 0, sizeof(struct sockaddr_in));
|
|
pin.sin_family = AF_INET;
|
|
|
|
for (;;)
|
|
{
|
|
tls_os_queue_receive(udp->udp_q, (void **)&msg, 0, 0);
|
|
//printf("\n msg =%d\n",msg);
|
|
switch((u32)msg)
|
|
{
|
|
case DEMO_MSG_WJOIN_SUCCESS:
|
|
break;
|
|
|
|
case DEMO_MSG_SOCKET_CREATE:
|
|
create_udp_socket_demo();
|
|
break;
|
|
|
|
case DEMO_MSG_WJOIN_FAILD:
|
|
if(udp->socket_num > 0)
|
|
{
|
|
udp->socket_num = 0;
|
|
udp->socket_ok = FALSE;
|
|
}
|
|
break;
|
|
|
|
case DEMO_MSG_SOCKET_RECEIVE_DATA:
|
|
break;
|
|
|
|
case DEMO_MSG_UART_RECEIVE_DATA:
|
|
if (-1 == udp->snd_data_len)
|
|
{
|
|
len = DEMO_UDP_BUF_SIZE;
|
|
}
|
|
else if(udp->snd_data_len != 0)
|
|
{
|
|
len = (udp->snd_data_len > DEMO_UDP_BUF_SIZE) ?
|
|
DEMO_UDP_BUF_SIZE : udp->snd_data_len;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
memset(udp->sock_tx, 'u', len);
|
|
|
|
if (DEMO_UDP_BROADCAST == udp->cast_mode)
|
|
{
|
|
pin.sin_addr.s_addr = htonl(0xffffffffUL); //IPADDR_BROADCAST
|
|
}
|
|
else if (DEMO_UDP_MUTICAST == udp->cast_mode)
|
|
{
|
|
MEMCPY((char *) & (pin.sin_addr.s_addr), (char *)MCASTIP, 4);
|
|
}
|
|
else
|
|
{
|
|
pin.sin_addr.s_addr = udp->ip_addr;
|
|
}
|
|
|
|
pin.sin_port = htons(udp->port);
|
|
|
|
ret = sendto(udp->socket_num, udp->sock_tx, len, 0, (struct sockaddr *)&pin, sizeof(struct sockaddr));
|
|
// printf("ret = %d\n",ret);
|
|
if (ret < 0)
|
|
{
|
|
printf("send err\n");
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (udp->snd_data_len != -1)
|
|
{
|
|
udp->snd_data_len -= ret;
|
|
}
|
|
}
|
|
if (udp->socket_ok && udp->snd_data_len != 0)
|
|
{
|
|
tls_os_time_delay(8);
|
|
tls_os_queue_send(udp->udp_q, (void *)DEMO_MSG_UART_RECEIVE_DATA, 0);
|
|
}
|
|
break;
|
|
|
|
case DEMO_MSG_SOCKET_ERR:
|
|
tls_os_time_delay(200);
|
|
printf("\nsocket err\n");
|
|
create_udp_socket_demo( );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|