1/*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 *    conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 *    of conditions and the following disclaimer in the documentation and/or other materials
13 *    provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 *    to endorse or promote products derived from this software without specific prior written
17 *    permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "lwip_test.h"
33#include "lwipopts.h"
34#include <arch/sys_arch.h>
35#include <lwip/sys.h>
36
37#define SRV_MSG "Hi, I am TCP server"
38#define CLI_MSG "Hi, I am TCP client"
39
40#define TEST_CASE 190
41#define STACK_PORT_9 2299
42#define TIME_OUT 10   // timeout 10s
43
44static char g_buf[BUF_SIZE + 1] = { 0 };
45
46static int SampleTcpServer()
47{
48#if LWIP_SOCKET_SELECT
49    g_testCase++;
50    int sfd, lsfd;
51    struct sockaddr_in srvAddr = { 0 };
52    struct sockaddr_in clnAddr = { 0 };
53    socklen_t clnAddrLen = sizeof(clnAddr);
54    fd_set fdsr;
55    struct timeval tv;
56    int ret;
57
58    /* tcp server */
59    lsfd = socket(AF_INET, SOCK_STREAM, 0);
60    LogPrintln("create server socket inet stream: %d", lsfd);
61    ICUNIT_ASSERT_NOT_EQUAL(lsfd, -1, 1);
62
63    srvAddr.sin_family = AF_INET;
64    srvAddr.sin_addr.s_addr = inet_addr(STACK_IP);
65    srvAddr.sin_port = htons(STACK_PORT_9);
66    ret = bind(lsfd, (struct sockaddr*)&srvAddr, sizeof(srvAddr));
67    LogPrintln("bind socket %d to %s:%d: %d", lsfd, inet_ntoa(srvAddr.sin_addr), ntohs(srvAddr.sin_port), ret);
68    ICUNIT_ASSERT_EQUAL(ret, 0, 2);
69
70    ret = listen(lsfd, 0);
71    LogPrintln("listen socket %d: %d", lsfd, ret);
72    ICUNIT_ASSERT_EQUAL(ret, 0, 3);
73
74    FD_ZERO(&fdsr);
75    FD_SET(lsfd, &fdsr);
76    // timeout setting
77    tv.tv_sec = TIME_OUT;
78    tv.tv_usec = 0;
79
80    ret = select(lsfd + 1, &fdsr, NULL, NULL, &tv);
81    if (ret < 0) {
82        LogPrintln("select error");
83        ICUNIT_ASSERT_EQUAL(-1, 0, 4);
84    } else if (ret == 0) {
85        LogPrintln("select timeout");
86        ICUNIT_ASSERT_EQUAL(-1, 0, 5);
87    }
88
89    sfd = accept(lsfd, (struct sockaddr*)&clnAddr, &clnAddrLen);
90    LogPrintln("accept socket %d: %d <%s:%d>", lsfd, sfd, inet_ntoa(clnAddr.sin_addr), ntohs(clnAddr.sin_port));
91    ICUNIT_ASSERT_NOT_EQUAL(sfd, -1, 6);
92
93    /* send */
94    (void)memset_s(g_buf, sizeof(g_buf), 0, sizeof(g_buf));
95    (void)strcpy_s(g_buf, sizeof(g_buf), SRV_MSG);
96    ret = send(sfd, g_buf, strlen(SRV_MSG), 0);
97    LogPrintln("server send on socket %d: %d", sfd, ret);
98    ICUNIT_ASSERT_EQUAL(ret, strlen(SRV_MSG), 7);
99
100    ret = closesocket(sfd);
101    ICUNIT_ASSERT_NOT_EQUAL(ret, -1, 8);
102    ret = closesocket(lsfd);
103    ICUNIT_ASSERT_NOT_EQUAL(ret, -1, 9);
104#endif
105    return 0;
106}
107
108static int SampleTcpClient()
109{
110#if LWIP_SOCKET_SELECT
111    g_testCase++;
112    int sfd;
113    struct sockaddr_in srvAddr = { 0 };
114    int ret;
115
116    /* tcp client connection */
117    sfd = socket(AF_INET, SOCK_STREAM, 0);
118    LogPrintln("create client socket inet stream: %d", sfd);
119    ICUNIT_ASSERT_NOT_EQUAL(sfd, -1, 10);
120
121    srvAddr.sin_family = AF_INET;
122    srvAddr.sin_addr.s_addr = inet_addr(PEER_IP);
123    srvAddr.sin_port = htons(STACK_PORT_9);
124    ret = connect(sfd, (struct sockaddr*)&srvAddr, sizeof(srvAddr));
125    LogPrintln("connect socket %d to %s:%d: %d", sfd, inet_ntoa(srvAddr.sin_addr), ntohs(srvAddr.sin_port), ret);
126    ICUNIT_ASSERT_EQUAL(ret, 0, 11);
127
128    /* recv */
129    (void)memset_s(g_buf, sizeof(g_buf), 0, sizeof(g_buf));
130    ret = recv(sfd, g_buf, sizeof(g_buf), 0);
131    LogPrintln("client recv on socket %d: %d", sfd, ret);
132    LogPrintln("cli:%s", g_buf);
133    ICUNIT_ASSERT_EQUAL(ret, strlen(SRV_MSG), 12);
134
135    ret = closesocket(sfd);
136    ICUNIT_ASSERT_NOT_EQUAL(ret, -1, 13);
137#endif
138    return 0;
139}
140
141static void TcpServerRoutine(void *p)
142{
143    (void)p;
144    (void)SampleTcpServer();
145}
146
147static void TcpClientRoutine(void *p)
148{
149    (void)p;
150    (void)SampleTcpClient();
151}
152
153void TcpTestSelect()
154{
155    LogPrintln("net_socket_test_009.c enter");
156    g_testCase = TEST_CASE;
157    int ret;
158    ret = sys_thread_new("tcp_server_select", TcpServerRoutine, NULL,
159        STACK_TEST_SIZE, TCPIP_THREAD_PRIO);
160    ICUNIT_ASSERT_NOT_EQUAL(ret, -1, 23);
161
162    ret = sys_thread_new("tcp_client_select", TcpClientRoutine, NULL,
163        STACK_TEST_SIZE, TCPIP_THREAD_PRIO);
164    ICUNIT_ASSERT_NOT_EQUAL(ret, -1, 24);
165}
166