/** * @file wm_udp_demo.c * * @brief udp demo * * @author dave * * Copyright (c) 2016 Winner Microelectronics Co., Ltd. */ #include #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