Toyomasa Watarai
/
Mbed-example-WS-W27
Mbed Cloud example program for workshop in W27 2018.
Embed:
(wiki syntax)
Show/hide line numbers
pal_socket_test.c
00001 /* 00002 * Copyright (c) 2016 ARM Limited. All rights reserved. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * Licensed under the Apache License, Version 2.0 (the License); you may 00005 * not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 00012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "pal.h" 00018 #include "pal_network.h" 00019 #include "unity.h" 00020 #include "unity_fixture.h" 00021 #include "PlatIncludes.h" 00022 #include "pal_test_main.h" 00023 #include "string.h" 00024 #ifdef __LINUX__ 00025 #include <netdb.h> 00026 #define test_getAddressInfo getAddressInfoIPv4 00027 #else 00028 #define test_getAddressInfo pal_getAddressInfo 00029 #endif 00030 00031 TEST_GROUP(pal_socket); 00032 00033 //Sometimes you may want to get local data in a module, 00034 //for example if you need to pass a reference. 00035 //However, you should usually avoid this. 00036 //extern int Counter; 00037 00038 #define PAL_NET_SUPPORT_LWIP 1 00039 #define PAL_NET_TEST_SERVER_NAME "www.arm.com" 00040 #define PAL_NET_TEST_SERVER_NAME_UDP "8.8.8.8" 00041 00042 00043 #define PAL_NET_TEST_SERVER_HTTP_PORT 80 00044 #define PAL_NET_TEST_SERVER_UDP_PORT 53 00045 #define PAL_NET_TEST_INCOMING_PORT 8002 00046 #define PAL_NET_TEST_INCOMING_PORT2 8989 00047 00048 #define PAL_NET_TEST_LOCAL_LOOPBACK_IF_INDEX 0 00049 PAL_PRIVATE void * g_networkInterface = NULL; 00050 PAL_PRIVATE uint32_t g_interfaceCTXIndex = 0; 00051 PAL_PRIVATE uint32_t s_callbackcounter = 0; 00052 00053 #define PAL_NET_TEST_SOCKETS 4 00054 PAL_PRIVATE palSocket_t g_testSockets[PAL_NET_TEST_SOCKETS] = {0,0,0,0}; 00055 00056 #define PAL_NET_TEST_GOOGLE_CDN_HOST "ajax.googleapis.com" /*! CDN host server */ 00057 #define PAL_NET_TEST_GOOGLE_CDN_HOST_PORT 80 /*! CDN host port */ 00058 #define PAL_NET_TEST_GOOGLE_CDN_REQUEST "GET /ajax/libs/jquery/3.2.1/jquery.js HTTP/1.0\r\nHost:" PAL_NET_TEST_GOOGLE_CDN_HOST "\r\n\r\n" /*! HTTP get request */ 00059 #define PAL_NET_TEST_BUFFERED_TCP_BUF_SIZE_SMALL 4 00060 #define PAL_NET_TEST_BUFFERED_TCP_BUF_SIZE_LARGE 1024 00061 #define PAL_NET_TEST_BUFFERED_UDP_BUF_SIZE_SMALL 64 00062 #define PAL_NET_TEST_BUFFERED_UDP_BUF_SIZE_LARGE 512 00063 #define PAL_NET_TEST_BUFFERED_UDP_PORT 2606 00064 #define PAL_NET_TEST_BUFFERED_UDP_MESSAGE_SIZE (1024 * 256) 00065 PAL_PRIVATE uint8_t *g_testRecvBuffer = NULLPTR; 00066 PAL_PRIVATE uint8_t *g_testSendBuffer = NULLPTR; 00067 00068 typedef struct pal_udp_test_data /*! structure used to hold state in UDP buffered tests */ 00069 { 00070 const size_t messageSize; 00071 const size_t bufferSize; 00072 const uint8_t startValue; 00073 palNetInterfaceInfo_t interfaceInfo; 00074 uint8_t currentValue; 00075 size_t totalSize; 00076 size_t chunkSize; 00077 } pal_udp_test_data_t; 00078 00079 TEST_SETUP(pal_socket) 00080 { 00081 uint32_t i = 0; 00082 palStatus_t status = PAL_SUCCESS; 00083 //This is run before *each test* 00084 pal_init(); 00085 if (g_networkInterface == NULL) 00086 { 00087 g_networkInterface = palTestGetNetWorkInterfaceContext(); 00088 status = pal_registerNetworkInterface(g_networkInterface , &g_interfaceCTXIndex); 00089 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 00090 } 00091 00092 for (i = 0; i < PAL_NET_TEST_SOCKETS; i++) 00093 { 00094 g_testSockets[i] = 0; 00095 } 00096 } 00097 00098 TEST_TEAR_DOWN(pal_socket) 00099 { 00100 uint32_t i = 0; 00101 for (i = 0; i < PAL_NET_TEST_SOCKETS; i++) 00102 { 00103 if (g_testSockets[i] != 0) 00104 { 00105 pal_close(&(g_testSockets[i])); 00106 } 00107 } 00108 00109 if (g_testRecvBuffer != NULLPTR) 00110 { 00111 free(g_testRecvBuffer); 00112 g_testRecvBuffer = NULLPTR; 00113 } 00114 if (g_testSendBuffer != NULLPTR) 00115 { 00116 free(g_testSendBuffer); 00117 g_testSendBuffer = NULLPTR; 00118 } 00119 00120 pal_destroy(); 00121 } 00122 00123 #define PAL_TEST_BUFFER_SIZE 50 00124 PAL_PRIVATE void socketCallback1( void * arg) 00125 { 00126 s_callbackcounter++; 00127 } 00128 00129 /*! \brief Test socket creation, destruction and modification, as well as getting address infromation and checking the blocking status of sockets. 00130 * 00131 ** \test 00132 * | # | Step | Expected | 00133 * |---|--------------------------------|-------------| 00134 * | 1 | Register a net interface using `pal_registerNetworkInterface`. | PAL_SUCCESS | 00135 * | 2 | Register a net interface using `pal_registerNetworkInterface`, and check that the ID is the same as the previous step. | PAL_SUCCESS | 00136 * | 3 | Get the interface address using `pal_getNetInterfaceInfo`. | PAL_SUCCESS | 00137 * | 4 | Create a blocking UDP socket using `pal_socket`. | PAL_SUCCESS | 00138 * | 5 | Create a blocking UDP socket using `pal_socket`. | PAL_SUCCESS | 00139 * | 6 | Create a non-blocking UDP socket using `pal_socket`. | PAL_SUCCESS | 00140 * | 7 | Create a blocking asynchronous TCP socket with `socketCallback1` as callback. | PAL_SUCCESS | 00141 * | 8 | Check the number of net interfaces registered using `pal_getNetInterfaceInfo`. | PAL_SUCCESS | 00142 * | 9 | Set the socket receive timeout using `pal_setSocketOptions`. | PAL_SUCCESS | 00143 * | 10 | Check that the sockets return the correct blocking status using `pal_isNonBlocking`. | PAL_SUCCESS | 00144 * | 11 | Check the `pal_getAddressInfo` function with an invalid address. | PAL_ERR_SOCKET_DNS_ERROR | 00145 * | 12 | Close all sockets. | PAL_SUCCESS | 00146 */ 00147 TEST(pal_socket, socketUDPCreationOptionsTest) 00148 { 00149 palStatus_t result = PAL_SUCCESS; 00150 uint32_t numInterface = 0; 00151 palNetInterfaceInfo_t interfaceInfo; 00152 uint32_t interfaceIndex = 0; 00153 uint32_t interfaceIndex2 = 0; 00154 uint32_t sockOptVal = 5000; 00155 uint32_t sockOptLen = sizeof(sockOptVal); 00156 palSocketAddress_t address = { 0 }; 00157 palSocketLength_t addrlen = 0; 00158 bool isNonBlocking = false; 00159 00160 memset(&interfaceInfo,0,sizeof(interfaceInfo)); 00161 // Check that re-adding the network interface returns the same index 00162 /*#1*/ 00163 result = pal_registerNetworkInterface(g_networkInterface, &interfaceIndex); 00164 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00165 00166 /*#2*/ 00167 result = pal_registerNetworkInterface(g_networkInterface, &interfaceIndex2); 00168 TEST_ASSERT_EQUAL_HEX(interfaceIndex, interfaceIndex2); 00169 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00170 00171 /*#3*/ 00172 result = pal_getNetInterfaceInfo(interfaceIndex, &interfaceInfo); 00173 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00174 TEST_PRINTF("Default interface address: %u %u %u %u \r\n", 00175 (unsigned char)interfaceInfo.address.addressData[2], 00176 (unsigned char)interfaceInfo.address.addressData[3], 00177 (unsigned char)interfaceInfo.address.addressData[4], 00178 (unsigned char)interfaceInfo.address.addressData[5]);; 00179 00180 00181 //Blocking 00182 /*#4*/ 00183 result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM , false, interfaceIndex, &g_testSockets[0]); 00184 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00185 /*#5*/ 00186 result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM , false, interfaceIndex, &g_testSockets[1]); 00187 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00188 //Non-blocking 00189 /*#6*/ 00190 result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM , true, interfaceIndex, &g_testSockets[3]); 00191 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00192 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 00193 /*#7*/ 00194 result = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_STREAM, false, interfaceIndex, socketCallback1, &g_testSockets[2]); 00195 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00196 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API 00197 00198 /*#8*/ 00199 result = pal_getNumberOfNetInterfaces(&numInterface); 00200 TEST_ASSERT_NOT_EQUAL(numInterface, 0); 00201 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00202 00203 /*#9*/ 00204 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO , &sockOptVal, sockOptLen); 00205 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00206 00207 /*#10*/ 00208 result = pal_isNonBlocking(g_testSockets[0],&isNonBlocking); 00209 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00210 TEST_ASSERT_EQUAL_HEX(isNonBlocking, false); 00211 00212 result = pal_isNonBlocking(g_testSockets[3], &isNonBlocking); 00213 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00214 TEST_ASSERT_EQUAL_HEX(isNonBlocking, true); 00215 00216 /*#11*/ 00217 result = pal_getAddressInfo("0.0.0.0", &address, &addrlen); 00218 TEST_ASSERT_EQUAL_HEX(PAL_ERR_SOCKET_DNS_ERROR , result); 00219 00220 /*#12*/ 00221 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 00222 result = pal_close(&g_testSockets[2]); 00223 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00224 00225 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API 00226 00227 result = pal_close(&g_testSockets[0]); 00228 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00229 result = pal_close(&g_testSockets[1]); 00230 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00231 result = pal_close(&g_testSockets[3]); 00232 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00233 result = pal_close(&g_testSockets[3]); //double close - should succeed 00234 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00235 } 00236 00237 00238 /*! \brief Test TCP socket creation, connection, send and receive with a test server. 00239 * 00240 ** \test 00241 * | # | Step | Expected | 00242 * |---|--------------------------------|-------------| 00243 * | 1 | Create a blocking TCP socket using `pal_socket`. | PAL_SUCCESS | 00244 * | 2 | Look up the IP address of the test server using `pal_getAddressInfo`. | PAL_SUCCESS | 00245 * | 3 | Set the port to a test port in the address structure using `pal_setSockAddrPort` and set timeout. | PAL_SUCCESS | 00246 * | 4 | Connect the socket to the test server using `pal_connect`. | PAL_SUCCESS | 00247 * | 5 | Send a test message (short HTTP request) to the test server using `pal_send`. | PAL_SUCCESS | 00248 * | 6 | Receive (blocking) the server's response using `pal_recv` and check it is HTTP. | PAL_SUCCESS | 00249 * | 7 | Close the socket. | PAL_SUCCESS | 00250 */ 00251 TEST(pal_socket, basicTCPclientSendRecieve) 00252 { 00253 palStatus_t result = PAL_SUCCESS; 00254 palSocketAddress_t address = { 0 }; 00255 const char message[] = "GET / HTTP/1.0\r\n\r\n"; 00256 size_t sent = 0; 00257 char buffer[100] = { 0 }; 00258 size_t read = 0; 00259 palSocketLength_t addrlen = 0; 00260 int timeout = 1000; 00261 00262 /*#1*/ 00263 00264 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[0]); 00265 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00266 00267 /*#2*/ 00268 result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME, &address, &addrlen); 00269 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00270 00271 /*#3*/ 00272 result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_HTTP_PORT); 00273 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00274 00275 00276 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO , &timeout, sizeof(timeout)); 00277 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00278 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO , &timeout, sizeof(timeout)); 00279 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00280 00281 00282 /*#4*/ 00283 result = pal_connect(g_testSockets[0], &address, 16); 00284 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00285 00286 /*#5*/ 00287 result = pal_send(g_testSockets[0], message, sizeof(message) - 1, &sent); 00288 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00289 00290 /*#6*/ 00291 result = pal_recv(g_testSockets[0], buffer, 99, &read); 00292 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00293 00294 TEST_ASSERT(read >= 4); 00295 TEST_ASSERT(buffer[0] == 'H' && buffer[1] == 'T'&& buffer[2] == 'T' && buffer[3] == 'P'); 00296 00297 /*#7*/ 00298 pal_close(&g_testSockets[0]); 00299 00300 } 00301 00302 /*! \brief Test UDP socket creation, connection, send and recieve with a test server. 00303 * 00304 ** \test 00305 * | # | Step | Expected | 00306 * |---|--------------------------------|-------------| 00307 * | 1 | Create a blocking UDP socket using `pal_socket`. | PAL_SUCCESS | 00308 * | 2 | Look up the IP address of the test server using `pal_getAddressInfo`. | PAL_SUCCESS | 00309 * | 3 | Set the port to a test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00310 * | 4 | Connect the socket to the test server using `pal_connect`. | PAL_SUCCESS | 00311 * | 5 | Send a test message (short DNS request) to the test server using `pal_send`. | PAL_SUCCESS | 00312 * | 6 | Receive (blocking) the server's response using `pal_recv`. | PAL_SUCCESS | 00313 * | 7 | Close the socket. | PAL_SUCCESS | 00314 */ 00315 TEST(pal_socket, basicUDPclientSendRecieve) 00316 { 00317 palStatus_t result = PAL_SUCCESS; 00318 palSocketAddress_t address = { 0 }; 00319 palSocketAddress_t address2 = { 0 }; 00320 uint8_t buffer[33] = { 0x8e, 0xde, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x61, 0x72, 0x73, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x63, 0x61, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 }; 00321 uint8_t buffer_in[10]; 00322 size_t sent = 0; 00323 size_t read = 0; 00324 size_t socket_timeout_ms = 5000; 00325 palSocketLength_t addrlen = 0; 00326 00327 /*#1*/ 00328 result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM , false, 0, &g_testSockets[0]); 00329 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00330 00331 /*#2*/ 00332 result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME_UDP, &address, &addrlen); 00333 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00334 00335 /*#3*/ 00336 result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_UDP_PORT); 00337 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00338 00339 /*#4*/ 00340 //We set a timeout for receiving so we won't get stuck in the test 00341 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO , &socket_timeout_ms, sizeof(socket_timeout_ms)); 00342 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00343 00344 /*#5*/ 00345 result = pal_sendTo(g_testSockets[0], buffer, sizeof(buffer), &address, 16, &sent); 00346 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00347 TEST_ASSERT_EQUAL(sent, sizeof(buffer)); 00348 00349 /*#6*/ 00350 result = pal_receiveFrom(g_testSockets[0], buffer_in, 10, &address2, &addrlen, &read); 00351 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00352 TEST_ASSERT_EQUAL(read, 10); 00353 00354 /*#7*/ 00355 pal_close(&g_testSockets[0]); 00356 } 00357 00358 00359 00360 00361 // This is an example showing how to check for a socket that has been closed remotely. 00362 #if 0 00363 PAL_PRIVATE void basicSocketScenario3Callback(void * arg) 00364 { 00365 char buffer[400]; 00366 size_t read = 0; 00367 palStatus_t result; 00368 00369 00370 s_callbackcounter++; 00371 result = pal_recv(g_testSockets[0], buffer, 999, &read); 00372 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00373 // If 0 bytes are read it means that the peer has performed an orderly shutdown so we must close the socket 00374 // to avoid ppoll from checking it. Checking a socket whose other end has been shut down causes ppoll to immediately return 00375 // with events == 0x1. 00376 if(read == 0) 00377 { 00378 pal_close(&g_testSockets[0]); 00379 } 00380 else 00381 { 00382 buffer[read] = '\0'; 00383 if(s_callbackcounter == 0) 00384 { 00385 TEST_ASSERT(read >= 4); 00386 TEST_ASSERT(buffer[0] == 'H' && buffer[1] == 'T'&& buffer[2] == 'T' && buffer[3] == 'P'); 00387 } 00388 } 00389 00390 } 00391 #endif 00392 palSemaphoreID_t s_semaphoreID = NULLPTR; 00393 00394 PAL_PRIVATE void socketCallback2(void * arg) 00395 { 00396 palStatus_t result; 00397 if(s_callbackcounter == 0) 00398 { 00399 result = pal_osSemaphoreRelease(s_semaphoreID); 00400 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00401 } 00402 s_callbackcounter++; 00403 00404 } 00405 00406 static int s_secondCallbackCounter = 0; 00407 PAL_PRIVATE void socketCallbackErr(void * arg) 00408 { 00409 s_secondCallbackCounter++; 00410 } 00411 00412 /*! \brief Test asynchronous socket callbacks. 00413 * 00414 ** \test 00415 * | # | Step | Expected | 00416 * |---|--------------------------------|-------------| 00417 * | 1 | Look up the IP address of the test server using `pal_getAddressInfo`. | PAL_SUCCESS | 00418 * | 2 | Create a blocking asynchronous TCP socket with `socketCallback2` as callback. | PAL_SUCCESS | 00419 * | 3 | Set port to a test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00420 * | 4 | Connect the socket to the test server using `pal_connect`. | PAL_SUCCESS | 00421 * | 5 | Send a test message (short HTTP request) to the test server using `pal_send`. | PAL_SUCCESS | 00422 * | 6 | Wait for a callback to release the semaphore when the response arrives. | PAL_SUCCESS | 00423 * | 7 | Receive (blocking) the server's response using `pal_recv` and check that the response is HTTP.| PAL_SUCCESS | 00424 * | 8 | Close the socket. | PAL_SUCCESS | 00425 */ 00426 TEST(pal_socket, basicSocketScenario3) 00427 { 00428 palStatus_t result = PAL_SUCCESS; 00429 palSocketAddress_t address = { 0 }; 00430 const char* message = "GET / HTTP/1.0\r\nHost:10.45.48.68:8000\r\n\r\n"; 00431 size_t sent = 0; 00432 char buffer[100] = { 0 }; 00433 size_t read = 0; 00434 s_callbackcounter = 0; 00435 palSocketLength_t addrlen = 0; 00436 int32_t countersAvailable; 00437 00438 result = pal_osSemaphoreCreate(1, &s_semaphoreID); 00439 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00440 result = pal_osSemaphoreWait(s_semaphoreID, 40000, &countersAvailable); 00441 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00442 00443 /*#1*/ 00444 result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME, &address, &addrlen); 00445 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00446 00447 00448 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 00449 /*#2*/ 00450 result = pal_asynchronousSocketWithArgument(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, socketCallback2, "socketCallback2Arg", &g_testSockets[0]); 00451 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00452 00453 s_secondCallbackCounter = 0; 00454 result = pal_asynchronousSocketWithArgument(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, socketCallbackErr, "socketCallback2Arg", &g_testSockets[1]); 00455 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00456 00457 TEST_ASSERT_EQUAL_HEX(0, s_secondCallbackCounter); 00458 /*#3*/ 00459 result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_HTTP_PORT); 00460 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00461 00462 /*#4*/ 00463 result = pal_connect(g_testSockets[0], &address, 16); 00464 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00465 00466 TEST_ASSERT_EQUAL_HEX(0, s_secondCallbackCounter); 00467 /*#5*/ 00468 result = pal_send(g_testSockets[0], message, strlen(message), &sent); 00469 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00470 00471 TEST_ASSERT_EQUAL_HEX(0, s_secondCallbackCounter); 00472 // Give a chance for the callback to be called. 00473 /*#6*/ 00474 result=pal_osSemaphoreWait(s_semaphoreID, 40000, &countersAvailable); 00475 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00476 00477 result=pal_osSemaphoreDelete(&s_semaphoreID); 00478 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00479 00480 /*#7*/ 00481 result = pal_recv(g_testSockets[0], buffer, 99, &read); 00482 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00483 TEST_ASSERT(read >= 4); 00484 TEST_ASSERT(buffer[0] == 'H' && buffer[1] == 'T'&& buffer[2] == 'T' && buffer[3] == 'P'); 00485 TEST_ASSERT(s_callbackcounter > 0); 00486 00487 00488 TEST_ASSERT_EQUAL_HEX(0, s_secondCallbackCounter); 00489 /*#8*/ 00490 pal_close(&g_testSockets[0]); 00491 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API 00492 } 00493 00494 00495 /*! \brief Tests two main secenarios: 00496 * 1. Use `pal_socketMiniSelect` to detect incoming traffic. 00497 * 2. Use `pal_socketMiniSelect` to check if a non-blocking socket has finished connecting. 00498 ** \test 00499 * | # | Step | Expected | 00500 * |---|--------------------------------|-------------| 00501 * | 1 | Create a blocking TCP socket using `pal_socket`. | PAL_SUCCESS | 00502 * | 2 | Create a blocking UDP socket using `pal_socket`. | PAL_SUCCESS | 00503 * | 3 | Look up the IP address of the `www.arm.com` server using `pal_getAddressInfo`. | PAL_SUCCESS | 00504 * | 4 | Set a port to the test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00505 * | 5 | Connect a socket to the test server using `pal_connect`. | PAL_SUCCESS | 00506 * | 6 | Send a test message (short HTTP request) to the test server using `pal_send`. | PAL_SUCCESS | 00507 * | 7 | Call `socketMiniSelect` with a timeout of 5 seconds, and check for correct socket state. Check `select` again when the data arrives.| PAL_SUCCESS | 00508 * | 8 | Receive (blocking) the server's response using `pal_recv` and check that the response is HTTP. | PAL_SUCCESS | 00509 * | 9 | Close the socket. | PAL_SUCCESS | 00510 * | 10 | Call `socketMiniSelect` with a timeout of 1 second and check for the correct socket state.| PAL_SUCCESS | 00511 * | 11 | Close the socket. | PAL_SUCCESS | 00512 * | 12 | Create a non-blocking TCP socket using `pal_socket`. | PAL_SUCCESS | 00513 * | 13 | Look up the IP address `192.0.2.0` (invalid IP address) using `pal_getAddressInfo`. | PAL_SUCCESS | 00514 * | 14 | Set the port to the test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00515 * | 15 | Connect to an invalid address and call `select`; check that the socket is not writable. | PAL_SUCCESS | 00516 * | 16 | Close the socket. | PAL_SUCCESS | 00517 * | 17 | Create a non-blocking TCP socket using `pal_socket`. | PAL_SUCCESS | 00518 * | 18 | Look up the IP address of the `www.arm.com` server using `pal_getAddressInfo`. | PAL_SUCCESS | 00519 * | 19 | Set the port to the test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00520 * | 20 | Connect and call `select` with a timeout of 2 seconds, and check that the socket is writable. | PAL_SUCCESS | 00521 * | 21 | Close the socket. | PAL_SUCCESS | 00522 */ 00523 TEST(pal_socket, basicSocketScenario4) 00524 { 00525 palStatus_t result = PAL_SUCCESS; 00526 palSocketAddress_t address = { 0 }; 00527 const char* message = "GET / HTTP/1.0\r\n\r\n"; 00528 size_t sent = 0; 00529 char buffer[100] = { 0 }; 00530 size_t read = 0; 00531 palSocketLength_t addlen = 0; 00532 uint32_t numSockets = 0; 00533 palSocket_t socketsToCheck[2] = { 0 }; 00534 pal_timeVal_t tv = {0}; 00535 uint8_t palSocketStatus[2] = { 0 }; 00536 00537 /*#1*/ 00538 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[0]); 00539 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00540 00541 /*#2*/ 00542 result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM , false, 0, &g_testSockets[1]); 00543 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00544 00545 /*#3*/ 00546 result = pal_getAddressInfo("www.arm.com", &address, &addlen); 00547 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00548 00549 /*#4*/ 00550 result = pal_setSockAddrPort(&address, 80); 00551 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00552 00553 /*#5*/ 00554 result = pal_connect(g_testSockets[0], &address, 16); 00555 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00556 00557 /*#6*/ 00558 result = pal_send(g_testSockets[0], message, strlen(message), &sent); 00559 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00560 00561 /*#7*/ 00562 socketsToCheck[0] = g_testSockets[0]; 00563 socketsToCheck[1] = g_testSockets[1]; 00564 tv.pal_tv_sec = 5; 00565 result = pal_socketMiniSelect(socketsToCheck, 2, &tv, palSocketStatus, &numSockets); // Data is expected to arrive during select 00566 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00567 if (numSockets == 0) // Clean up to prevent resource leak. 00568 { 00569 pal_close(&g_testSockets[0]); 00570 pal_close(&g_testSockets[1]); 00571 } 00572 TEST_ASSERT( 0 < numSockets); 00573 TEST_ASSERT(0< palSocketStatus[0] ); 00574 TEST_ASSERT(PAL_NET_SELECT_IS_TX(palSocketStatus, 0) || PAL_NET_SELECT_IS_RX(palSocketStatus, 0) || PAL_NET_SELECT_IS_ERR(palSocketStatus, 0)); 00575 TEST_ASSERT((palSocketStatus[1] & (PAL_NET_SOCKET_SELECT_RX_BIT | PAL_NET_SOCKET_SELECT_ERR_BIT)) == 0); 00576 TEST_ASSERT_FALSE((PAL_NET_SELECT_IS_RX(palSocketStatus,1))); 00577 TEST_ASSERT_FALSE((PAL_NET_SELECT_IS_ERR(palSocketStatus, 1))); 00578 00579 00580 palSocketStatus[0] = 0; 00581 palSocketStatus[1] = 0; 00582 result = pal_socketMiniSelect(socketsToCheck, 2, &tv, palSocketStatus, &numSockets); // Check what happens when you call `select` when the data has already arrived. 00583 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00584 if (numSockets == 0) // Clean up to prevent resource leak. 00585 { 00586 pal_close(&g_testSockets[0]); 00587 pal_close(&g_testSockets[1]); 00588 } 00589 TEST_ASSERT(0 < numSockets); 00590 TEST_ASSERT(0< palSocketStatus[0]); 00591 TEST_ASSERT((palSocketStatus[1] & (PAL_NET_SOCKET_SELECT_RX_BIT | PAL_NET_SOCKET_SELECT_ERR_BIT)) == 0); 00592 TEST_ASSERT_FALSE((PAL_NET_SELECT_IS_RX(palSocketStatus, 1))); 00593 TEST_ASSERT_FALSE((PAL_NET_SELECT_IS_ERR(palSocketStatus, 1))); 00594 00595 00596 00597 /*#8*/ 00598 00599 result = pal_recv(g_testSockets[0], buffer, 99, &read); 00600 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00601 00602 TEST_ASSERT(read >= 4); 00603 TEST_ASSERT(buffer[0] == 'H' && buffer[1] == 'T'&& buffer[2] == 'T' && buffer[3] == 'P'); 00604 00605 /*#9*/ 00606 pal_close(&g_testSockets[0]); 00607 00608 /*#10*/ 00609 numSockets = 0; 00610 palSocketStatus[0] =0; 00611 palSocketStatus[1] =0; 00612 socketsToCheck[0] = g_testSockets[1]; 00613 socketsToCheck[1] = 0; 00614 tv.pal_tv_sec = 1; 00615 00616 result = pal_socketMiniSelect(socketsToCheck, 1, &tv, palSocketStatus, &numSockets); 00617 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00618 TEST_ASSERT((palSocketStatus[0] & (PAL_NET_SOCKET_SELECT_RX_BIT | PAL_NET_SOCKET_SELECT_ERR_BIT)) == 0); 00619 TEST_ASSERT_FALSE((PAL_NET_SELECT_IS_RX(palSocketStatus, 1))); 00620 TEST_ASSERT_FALSE((PAL_NET_SELECT_IS_ERR(palSocketStatus, 1))); 00621 00622 /*#11*/ 00623 pal_close(&g_testSockets[1]); 00624 00625 // Non-responsive socket connection 00626 /*#12*/ 00627 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, &g_testSockets[2]); 00628 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00629 00630 numSockets = 0; 00631 palSocketStatus[0] =0; 00632 palSocketStatus[1] =0; 00633 socketsToCheck[0] = g_testSockets[2]; 00634 socketsToCheck[1] = 0; 00635 tv.pal_tv_sec = 1; 00636 00637 /*#13*/ 00638 result = pal_getAddressInfo("192.0.2.0", &address, &addlen); // Address intended for testing (not a real address); we don't expect a connection. 00639 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00640 00641 /*#14*/ 00642 result = pal_setSockAddrPort(&address, 80); 00643 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00644 00645 result = pal_connect(g_testSockets[2], &address, 16); 00646 //TEST_ASSERT_EQUAL_HEX( PAL_ERR_SOCKET_IN_PROGRES, result); // Comment back in when a non-blocking connection is enabled on mbed OS 00647 00648 /*#15*/ 00649 result = pal_socketMiniSelect(socketsToCheck, 1, &tv, palSocketStatus, &numSockets); 00650 00651 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00652 TEST_ASSERT( 0 == numSockets); 00653 TEST_ASSERT(0 == palSocketStatus[0] ); 00654 00655 /*#16*/ 00656 pal_close(&g_testSockets[2]); 00657 00658 /*#17*/ 00659 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, &g_testSockets[2]); 00660 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00661 00662 numSockets = 0; 00663 palSocketStatus[0] =0; 00664 palSocketStatus[1] =0; 00665 socketsToCheck[0] = g_testSockets[2]; 00666 socketsToCheck[1] = 0; 00667 tv.pal_tv_sec = 2; 00668 00669 /*#18*/ 00670 result = pal_getAddressInfo("www.arm.com", &address, &addlen); // Address intended for testing (not a real address); we don't expect a connection. 00671 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00672 00673 /*#19*/ 00674 result = pal_setSockAddrPort(&address, 80); 00675 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00676 00677 result = pal_connect(g_testSockets[2], &address, 16); 00678 //TEST_ASSERT_EQUAL_HEX( PAL_ERR_SOCKET_IN_PROGRES, result); // Comment back in when a non-blocking connection is enabled on mbed OS 00679 00680 /*#20*/ 00681 result = pal_socketMiniSelect(socketsToCheck, 1, &tv, palSocketStatus, &numSockets); 00682 /*#21*/ 00683 pal_close(&g_testSockets[2]); 00684 00685 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 00686 TEST_ASSERT( 1 == numSockets); 00687 TEST_ASSERT( PAL_NET_SOCKET_SELECT_TX_BIT == (palSocketStatus[0]& ( PAL_NET_SOCKET_SELECT_TX_BIT) )); 00688 TEST_ASSERT((PAL_NET_SELECT_IS_TX(palSocketStatus, 0))); 00689 } 00690 00691 00692 typedef struct palNetTestThreadData{ 00693 palSemaphoreID_t sem1; 00694 palSemaphoreID_t sem2; 00695 uint16_t port; 00696 } palNetTestThreadData_t; 00697 00698 char s_rcv_buffer[20] = {0}; 00699 char s_rcv_buffer2[50] = {0}; 00700 00701 void palNetClientFunc(void const *argument) 00702 { 00703 palStatus_t result = PAL_SUCCESS; 00704 int32_t tmp = 0; 00705 size_t sent = 0; 00706 size_t read = 0; 00707 palNetTestThreadData_t* dualSem = (palNetTestThreadData_t*)argument; 00708 palSocketLength_t addrlen = 16; 00709 //palSocketAddress_t address = { 0 }; 00710 palNetInterfaceInfo_t interfaceInfo; 00711 const char* message = "GET / HTTP/1.0\r\n\r\n"; 00712 00713 /*#C1*/ 00714 result = pal_osSemaphoreWait(dualSem->sem1, 500, &tmp); 00715 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00716 00717 /*#C2*/ 00718 result = pal_getNetInterfaceInfo(PAL_NET_TEST_LOCAL_LOOPBACK_IF_INDEX, &interfaceInfo); 00719 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00720 00721 /*#C3*/ 00722 uint16_t incoming_port = dualSem->port; 00723 TEST_PRINTF("client port = %u", incoming_port); 00724 result = pal_setSockAddrPort(&(interfaceInfo.address), incoming_port); 00725 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00726 00727 /*#C4*/ 00728 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[2]); 00729 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00730 00731 /*#C5*/ 00732 result = pal_connect(g_testSockets[2], &(interfaceInfo.address), addrlen); 00733 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00734 00735 /*#C6*/ 00736 result = pal_send(g_testSockets[2], message, 18, &sent); 00737 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00738 00739 /*#C7*/ 00740 result = pal_recv(g_testSockets[2], s_rcv_buffer, 15, &read); 00741 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00742 TEST_PRINTF(s_rcv_buffer); 00743 00744 /*#C8*/ 00745 pal_close(&g_testSockets[2]); 00746 00747 result = pal_osSemaphoreRelease(dualSem->sem2); 00748 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00749 } 00750 00751 /*! \brief /b ServerSocketScenario tests a TCP client-server scenario using device loopback. 00752 * 00753 * \note The test steps are divided into those in the server main thread (S1..S13) and those in the client thread (C1..C8). 00754 * The sequence below is an approximation of the actual order of execution. 00755 * 00756 ** \test 00757 * | # | Step | Expected | 00758 * |---|--------------------------------|-------------| 00759 * | S1 | Create a blocking TCP server socket using `pal_socket`. | PAL_SUCCESS | 00760 * | S2 | Create a blocking TCP socket using `pal_socket`. | PAL_SUCCESS | 00761 * | S3 | Look up the IP address of loopback using `pal_getAddressInfo`. | PAL_SUCCESS | 00762 * | S4 | Set the port to test port in address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00763 * | S5 | Bind the server socket to the port and address using `pal_bind`. | PAL_SUCCESS | 00764 * | S6 | Create synchronization sepmaphores and set count to 0. | PAL_SUCCESS | 00765 * | S7 | Create a client thread with `BelowNormal` priority running `palNetClientFunc`. | PAL_SUCCESS | 00766 * | C1 | Client thread blocks on client sepmaphore s1. | PAL_SUCCESS | 00767 * | S8 | Listen to the server port using `pal_listen`. | PAL_SUCCESS | 00768 * | S9 | Release the client sepmahore s1. | PAL_SUCCESS | 00769 * | S10 | Call `accept` (blocking) to accept a new connection (retry in case of failure). | PAL_SUCCESS | 00770 * | C2 | Look up the IP address of the loopback using `pal_getAddressInfo`. | PAL_SUCCESS | 00771 * | C3 | Set the port to test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00772 * | C4 | Create a blocking TCP socket using `pal_socket`. | PAL_SUCCESS | 00773 * | C5 | Connect to the server using `pal_connect`. | PAL_SUCCESS | 00774 * | C6 | Send data to server. | PAL_SUCCESS | 00775 * | S11 | Receive data from the client. | PAL_SUCCESS | 00776 * | S12 | Send data to the client. | PAL_SUCCESS | 00777 * | C7 | Receive data from the server. | PAL_SUCCESS | 00778 * | C8 | Client thread cleanup - close the socket and release the semaphore. | PAL_SUCCESS | 00779 * | S13 | Cleanup: close sockets and delete semaphores. | PAL_SUCCESS | 00780 */ 00781 00782 TEST(pal_socket, ServerSocketScenario) 00783 { 00784 palStatus_t result = PAL_SUCCESS; 00785 palSocketAddress_t address2 = { 0 }; 00786 const char* messageOut = "HTTP/1.0 200 OK"; 00787 size_t sent = 0; 00788 size_t read = 0; 00789 palSocketLength_t addrlen = 16; 00790 00791 palSemaphoreID_t semaphoreID = NULLPTR; 00792 palSemaphoreID_t semaphoreID2 = NULLPTR; 00793 palNetTestThreadData_t dualSem = {0}; 00794 palThreadID_t threadID1 = NULLPTR; 00795 int32_t tmp = 0; 00796 palNetInterfaceInfo_t interfaceInfo; 00797 memset(&interfaceInfo,0,sizeof(interfaceInfo)); 00798 00799 00800 /*#S1*/ 00801 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM_SERVER , false, 0, &g_testSockets[0]); 00802 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00803 00804 /*#S2*/ 00805 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[1]); 00806 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00807 00808 /*#S3*/ 00809 result = pal_getNetInterfaceInfo(PAL_NET_TEST_LOCAL_LOOPBACK_IF_INDEX, &interfaceInfo); 00810 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00811 00812 TEST_PRINTF("interface addr: %u %u %u %u \r\n", 00813 (unsigned char)interfaceInfo.address.addressData[2], 00814 (unsigned char)interfaceInfo.address.addressData[3], 00815 (unsigned char)interfaceInfo.address.addressData[4], 00816 (unsigned char)interfaceInfo.address.addressData[5]);; 00817 /*#S4*/ 00818 uint32_t rand_number = 0; 00819 uint16_t incoming_port; 00820 00821 for (int i=0; i<5; i++) { 00822 pal_osRandom32bit(&rand_number); 00823 incoming_port = (uint16_t)(35400 + (rand_number % (40000 - 35400))); 00824 TEST_PRINTF("server port = %u", incoming_port); 00825 00826 result = pal_setSockAddrPort(&(interfaceInfo.address), incoming_port); 00827 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00828 00829 /*#S5*/ 00830 result = pal_bind(g_testSockets[0], &(interfaceInfo.address), interfaceInfo.addressSize); 00831 00832 if (PAL_SUCCESS == result) { 00833 TEST_PRINTF("bind succeeded on port %u", incoming_port); 00834 break; 00835 } else { 00836 TEST_PRINTF("bind failed on port %u", incoming_port); 00837 } 00838 } 00839 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00840 00841 /*#S6*/ 00842 00843 // start client thread to connect to the server. 00844 result = pal_osSemaphoreCreate(1 ,&semaphoreID); 00845 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00846 result = pal_osSemaphoreWait(semaphoreID, 1000, &tmp); 00847 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00848 00849 00850 result = pal_osSemaphoreCreate(1 ,&semaphoreID2); 00851 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00852 result = pal_osSemaphoreWait(semaphoreID2, 1000, &tmp); 00853 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00854 00855 dualSem.sem1 = semaphoreID; 00856 dualSem.sem2 = semaphoreID2; 00857 dualSem.port = incoming_port; 00858 00859 /*#S7*/ 00860 result = pal_osThreadCreateWithAlloc(palNetClientFunc, &dualSem , PAL_osPriorityBelowNormal, PAL_TEST_THREAD_STACK_SIZE, NULL, &threadID1); 00861 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00862 00863 /*#S8*/ 00864 result = pal_listen(g_testSockets[0], 10); 00865 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00866 00867 /*#S9*/ 00868 result = pal_osSemaphoreRelease(dualSem.sem1); 00869 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00870 00871 00872 TEST_PRINTF("waiting for connection:\r\n"); 00873 /*#S10*/ 00874 result = pal_accept(g_testSockets[0], &address2, &addrlen, &g_testSockets[1]); 00875 TEST_PRINTF("after accept: %" PRIu32 "\r\n", result); 00876 if (PAL_SUCCESS != result ) 00877 { 00878 result = pal_accept(g_testSockets[0], &address2, &addrlen, &g_testSockets[1]); 00879 TEST_PRINTF("after accept: %" PRIu32 "\r\n",result); 00880 } 00881 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00882 00883 /*#S11*/ 00884 result = pal_recv(g_testSockets[1], s_rcv_buffer2, 49, &read); 00885 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00886 TEST_PRINTF(s_rcv_buffer2); 00887 00888 /*#S12*/ 00889 result = pal_send(g_testSockets[1], messageOut, 15, &sent); 00890 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00891 00892 00893 //cleanup 00894 00895 /*#S13*/ 00896 pal_close(&g_testSockets[1]); 00897 pal_close(&g_testSockets[0]); 00898 00899 result = pal_osSemaphoreWait(semaphoreID2, 5000, &tmp); 00900 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00901 pal_osDelay(2000); 00902 pal_osThreadTerminate(&threadID1); 00903 result = pal_osSemaphoreDelete(&semaphoreID); 00904 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00905 TEST_ASSERT_EQUAL_HEX(NULL, semaphoreID); 00906 00907 result = pal_osSemaphoreDelete(&semaphoreID2); 00908 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00909 TEST_ASSERT_EQUAL_HEX(NULL, semaphoreID2); 00910 } 00911 00912 00913 00914 PAL_PRIVATE volatile uint32_t s_callbackCounterNonBlock = 0; 00915 00916 PAL_PRIVATE void nonBlockCallback(void * arg) 00917 { 00918 s_callbackCounterNonBlock++; 00919 } 00920 00921 #define PAL_NET_TEST_HTTP_HEADER_LEN 5 00922 00923 /*! \brief /b nonBlockingAsyncTest checks the asynchronous- nonblocking socket scenario. 00924 ** \test 00925 * | # | Step | Expected | 00926 * |---|--------------------------------|-------------| 00927 * | 1 | Look up the IP address of the test server using `pal_getAddressInfo`. | PAL_SUCCESS | 00928 * | 2 | Create an asynchronous non-blocking TCP socket with `nonBlockCallback` as callback. | PAL_SUCCESS | 00929 * | 3 | Set the port to test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 00930 * | 4 | Connect the socket. | PAL_SUCCESS or PAL_ERR_SOCKET_IN_PROGRES | 00931 * | 5 | Send a test message to the test server using `pal_send` (repeat until success). | PAL_SUCCESS or PAL_ERR_SOCKET_IN_PROGRES | 00932 * | 6 | Wait for the callback and receive server response using `pal_recv` (repeat until success). | PAL_SUCCESS or PAL_ERR_SOCKET_WOULD_BLOCK| 00933 * | 7 | Close the socket. | PAL_SUCCESS | 00934 */ 00935 TEST(pal_socket, nonBlockingAsyncTest) 00936 { 00937 palStatus_t result = PAL_SUCCESS; 00938 palSocketAddress_t address = { 0 }; 00939 const char* message = "GET / HTTP/1.0\r\nHost:10.45.48.68:8000\r\n\r\n"; 00940 size_t sent = 0; 00941 char buffer[100] = { 0 }; 00942 size_t read = 0; 00943 s_callbackcounter = 0; 00944 palSocketLength_t addrlen = 0; 00945 int32_t waitIterations = 0; 00946 00947 /*#1*/ 00948 result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME, &address, &addrlen); 00949 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00950 00951 #if PAL_NET_ASYNCHRONOUS_SOCKET_API 00952 /*#2*/ 00953 result = pal_asynchronousSocketWithArgument(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, nonBlockCallback, "non-blockSocketCallbackArg", &g_testSockets[0]); 00954 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00955 00956 /*#3*/ 00957 result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_HTTP_PORT); 00958 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00959 00960 /*#4*/ 00961 result = pal_connect(g_testSockets[0], &address, 16); 00962 if (PAL_ERR_SOCKET_IN_PROGRES == result) 00963 { 00964 result = pal_connect(g_testSockets[0], &address, 16); 00965 if ((result != PAL_SUCCESS) && (result != PAL_ERR_SOCKET_ALREADY_CONNECTED ) && (result != PAL_ERR_SOCKET_IN_PROGRES ) && (result != PAL_ERR_SOCKET_WOULD_BLOCK )) // check expected result codes.(connection should either be in progress or connected already) 00966 { 00967 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00968 } 00969 pal_osDelay(400); 00970 } 00971 else 00972 { 00973 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00974 } 00975 s_callbackCounterNonBlock = 0; 00976 00977 /*#5*/ 00978 result = pal_send(g_testSockets[0], message, strlen(message), &sent); 00979 00980 while (PAL_ERR_SOCKET_IN_PROGRES == result) 00981 { 00982 pal_osDelay(100); 00983 result = pal_send(g_testSockets[0], message, strlen(message), &sent); 00984 } 00985 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 00986 00987 /*#6*/ 00988 result = pal_recv(g_testSockets[0], buffer, PAL_NET_TEST_HTTP_HEADER_LEN, &read); // may block 00989 while ((PAL_ERR_SOCKET_WOULD_BLOCK == result) && (10 > waitIterations )) 00990 { 00991 s_callbackCounterNonBlock = 0; 00992 while (s_callbackCounterNonBlock == 0) 00993 { 00994 waitIterations++; 00995 pal_osDelay(100); 00996 } 00997 result = pal_recv(g_testSockets[0], buffer, PAL_NET_TEST_HTTP_HEADER_LEN, &read); // shouldnt block 00998 } 00999 01000 /*#7*/ 01001 pal_close(&g_testSockets[0]); 01002 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01003 TEST_ASSERT(read >= 4); 01004 TEST_ASSERT(buffer[0] == 'H' && buffer[1] == 'T'&& buffer[2] == 'T' && buffer[3] == 'P'); 01005 TEST_ASSERT(s_callbackCounterNonBlock > 0); 01006 01007 #endif // PAL_NET_ASYNCHRONOUS_SOCKET_API 01008 } 01009 01010 /*! \brief /b tProvUDPTest tests UDP socket send/receive and checks that we get the correct error for receive timeout. 01011 ** \test 01012 * | # | Step | Expected | 01013 * |---|--------------------------------|-------------| 01014 * | 1 | Create a blocking UDP socket using `pal_socket`. | PAL_SUCCESS | 01015 * | 2 | Look up the IP address of the test server using `pal_getAddressInfo`. | PAL_SUCCESS | 01016 * | 3 | Set the port to test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 01017 * | 4 | Set socket timeouts using `pal_setSocketOptions`. | PAL_SUCCESS | 01018 * | 5 | Send a test message (short HTTP request) to test the server using `pal_send`. | PAL_SUCCESS | 01019 * | 6 | Receive the (blocking) server response using `pal_recv`. | PAL_SUCCESS | 01020 * | 7 | Receive the (blocking) server response again using `pal_recv` and fail. | PAL_ERR_SOCKET_WOULD_BLOCK | 01021 * | 8 | Close the socket. | PAL_SUCCESS | 01022 */ 01023 TEST(pal_socket, tProvUDPTest) 01024 { 01025 palStatus_t result = PAL_SUCCESS; 01026 palSocketAddress_t address = { 0,{0} }; 01027 uint8_t buffer[100] = { 0 }; 01028 uint8_t buffer_dns[33] = { 0x8e, 0xde, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x61, 0x72, 0x73, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x63, 0x61, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 }; 01029 size_t sent = 0; 01030 size_t read = 0; 01031 palSocketLength_t addrlen = 16; 01032 int timeout = 1000; 01033 01034 /*#1*/ 01035 result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM , false, 0, &g_testSockets[0]); 01036 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 01037 01038 /*#2*/ 01039 result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME_UDP, &address, &addrlen); 01040 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 01041 01042 /*#3*/ 01043 result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_UDP_PORT); 01044 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 01045 01046 /*#4*/ 01047 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO , &timeout, sizeof(timeout)); 01048 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 01049 01050 timeout = 1000; 01051 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO , &timeout, sizeof(timeout)); 01052 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 01053 01054 /*#5*/ 01055 result = pal_sendTo(g_testSockets[0], buffer_dns, sizeof(buffer_dns), &address, addrlen, &sent); 01056 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 01057 TEST_ASSERT_EQUAL_HEX(sent, sizeof(buffer_dns)); 01058 01059 /*#6*/ 01060 result = pal_receiveFrom(g_testSockets[0], buffer, 16, NULL, NULL, &read); 01061 TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result); 01062 TEST_ASSERT_EQUAL(read, 16); 01063 01064 /*#7*/ 01065 result = pal_receiveFrom(g_testSockets[0], buffer, 100, NULL, NULL, &read); // should get timeout 01066 TEST_ASSERT_EQUAL_HEX(result, PAL_ERR_SOCKET_WOULD_BLOCK ); 01067 01068 /*#8*/ 01069 pal_close(&g_testSockets[0]); 01070 } 01071 01072 01073 void socket_event_handler(void* arg) 01074 { 01075 01076 } 01077 01078 01079 01080 #define PAL_COAP_NET_TEST_SERVER_NAME "coap-integration-lab.dev.mbed.com" 01081 #define PAL_COAP_NET_TEST_SERVER_HTTP_PORT 5684 01082 #define WAIT_TIME_ASYNC_SEC 0 01083 #define RETRY_COUNT 10 01084 /*! \brief /b PalTestAPPTestt tests TCP async connection to COAP server. 01085 ** \test 01086 * | # | Step | Expected | 01087 * |---|--------------------------------|-------------| 01088 * | 1 | Create a blocking UDP socket using `pal_socket`. | PAL_SUCCESS | 01089 * | 2 | Look up the IP address of the test server using `pal_getAddressInfo`. | PAL_SUCCESS | 01090 * | 3 | Set the port to test port in the address structure using `pal_setSockAddrPort`. | PAL_SUCCESS | 01091 * | 4 | Get the local unit IP using `pal_getSockAddrIPV4Addr`. | PAL_SUCCESS | 01092 * | 5 | Get the number of connected interfaces using `pal_getNumberOfNetInterfaces`. | PAL_SUCCESS | 01093 * | 6 | Get the interface info using `pal_getNetInterfaceInfo`. | PAL_SUCCESS | 01094 * | 7 | Set the async socket `pal_asynchronousSocket`. | PAL_SUCCESS | 01095 * | 8| Connect to the socket. | PAL_SUCCESS Or PAL_ERR_SOCKET_IN_PROGRES| 01096 * | 9| If step 10 failed, check if socket was connected using `pal_socketMiniSelect`. | PAL_SUCCESS | 01097 * | 10| If mini select passes, try sending data to socket. | PAL_SUCCESS | 01098 * | 11 | Close the socket. | PAL_SUCCESS | 01099 */ 01100 TEST(pal_socket, PalMiniSelectNoBlockingTcpConnection) 01101 { 01102 palStatus_t status = PAL_SUCCESS; 01103 palSocketLength_t _socket_address_len = 0; 01104 palSocketAddress_t _socket_address = { 0 }; 01105 palSocket_t _socket = 0; 01106 palIpV4Addr_t interface_address4 = {0}; 01107 palIpV6Addr_t interface_address6 = {0}; 01108 uint32_t interface_count; 01109 palNetInterfaceInfo_t interface_info; 01110 palSocketAddress_t bind_address; 01111 pal_timeVal_t zeroTime = {WAIT_TIME_ASYNC_SEC, 0}; 01112 uint32_t socketsSet = 0; 01113 uint8_t socketStatus[1] = { 0 }; 01114 int i = 0; 01115 01116 /*#1*/ 01117 memset(&interface_info,0,sizeof(interface_info)); 01118 memset(&bind_address, 0, sizeof(palSocketAddress_t)); 01119 01120 /*#2*/ 01121 status = pal_getAddressInfo(PAL_COAP_NET_TEST_SERVER_NAME, &_socket_address, &_socket_address_len); 01122 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 01123 01124 /*#3*/ 01125 status = pal_setSockAddrPort(&_socket_address, PAL_COAP_NET_TEST_SERVER_HTTP_PORT); 01126 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 01127 /*#4*/ 01128 if (PAL_AF_INET == _socket_address.addressType) //if address is IPV4 extract ipv4 address. 01129 { 01130 status = pal_getSockAddrIPV4Addr(&_socket_address, interface_address4); 01131 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 01132 } 01133 else if (PAL_AF_INET6 == _socket_address.addressType){ // address is IPV6 - extract IPV6 address. 01134 status = pal_getSockAddrIPV6Addr(&_socket_address, interface_address6); 01135 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 01136 } 01137 else 01138 { 01139 // unexpected address type ---> error 01140 TEST_ASSERT(((PAL_AF_INET6 == _socket_address.addressType) || (PAL_AF_INET == _socket_address.addressType))); 01141 } 01142 01143 /*#5*/ 01144 status = pal_getNumberOfNetInterfaces(&interface_count); 01145 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 01146 01147 /*#6*/ 01148 status = pal_getNetInterfaceInfo(g_interfaceCTXIndex, &interface_info); 01149 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 01150 01151 /*#7*/ 01152 status = pal_asynchronousSocket((palSocketDomain_t )_socket_address.addressType, (palSocketType_t )PAL_SOCK_STREAM, true, (uint32_t)g_interfaceCTXIndex, (palAsyncSocketCallback_t )&socket_event_handler, &_socket); 01153 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 01154 01155 /*#8*/ 01156 status = pal_connect(_socket, &_socket_address, _socket_address_len); 01157 pal_osDelay(300); 01158 01159 /*#9*/ 01160 if(status != PAL_SUCCESS) 01161 { 01162 for(i = 0; i < RETRY_COUNT ; i++) 01163 { 01164 status = pal_socketMiniSelect(&_socket, 1, &zeroTime, socketStatus, &socketsSet); 01165 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 01166 if(socketsSet > 0) 01167 { 01168 TEST_ASSERT_EQUAL_HEX(socketsSet >= 1, 1); 01169 break; 01170 } 01171 pal_osDelay(100); 01172 } 01173 } 01174 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 01175 01176 /*#10*/ 01177 { 01178 uint8_t message[] = { 0x16 ,0x03 ,0x01 ,0x00 ,0x79 ,0x01 ,0x00 ,0x00 ,0x75 ,0x03 ,0x03 ,0x59 ,0x11 ,0xae ,0xef ,0x4f 01179 ,0x6f ,0x5f ,0xd7 ,0x0f ,0x50 ,0x7c ,0x05 ,0x37 ,0xe3 ,0xd9 ,0x47 ,0x82 ,0x8e ,0x64 ,0x75 ,0x3c 01180 ,0xa4 ,0xca ,0xef ,0x45 ,0x25 ,0x4e ,0x36 ,0xdf ,0x5d ,0xbf ,0x96 ,0x00 ,0x00 ,0x04 ,0xc0 ,0xac 01181 ,0x00 ,0xff ,0x01 ,0x00 ,0x00 ,0x48 ,0x00 ,0x0d ,0x00 ,0x16 ,0x00 ,0x14 ,0x06 ,0x03 ,0x06 ,0x01 01182 ,0x05 ,0x03 ,0x05 ,0x01 ,0x04 ,0x03 ,0x04 ,0x01 ,0x03 ,0x03 ,0x03 ,0x01 ,0x02 ,0x03 ,0x02 ,0x01 01183 ,0x00 ,0x0a ,0x00 ,0x18 ,0x00 ,0x16 ,0x00 ,0x19 ,0x00 ,0x1c ,0x00 ,0x18 ,0x00 ,0x1b ,0x00 ,0x17 01184 ,0x00 ,0x16 ,0x00 ,0x1a ,0x00 ,0x15 ,0x00 ,0x14 ,0x00 ,0x13 ,0x00 ,0x12 ,0x00 ,0x0b ,0x00 ,0x02 01185 ,0x01 ,0x00 ,0x00 ,0x16 ,0x00 ,0x00 ,0x00 ,0x17 ,0x00 ,0x00 ,0x00 ,0x23 ,0x00 ,0x00}; 01186 01187 size_t sent = 0; 01188 for(i = 0; i < RETRY_COUNT; i++) 01189 { 01190 status = pal_send(_socket, message, sizeof(message), &sent); 01191 if(status == PAL_SUCCESS) 01192 { 01193 break; 01194 } 01195 pal_osDelay(100); 01196 } 01197 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 01198 01199 } 01200 01201 /*#10*/ 01202 pal_close(&_socket); 01203 } 01204 01205 PAL_PRIVATE void fillUDPTestBuffer(pal_udp_test_data_t *data, uint8_t* buffer) 01206 { 01207 memset(buffer, 0, data->bufferSize); 01208 data->chunkSize = (data->messageSize - data->totalSize > data->bufferSize) ? data->bufferSize : (data->messageSize - data->totalSize); 01209 memset(buffer, ++(data->currentValue), data->chunkSize); 01210 data->totalSize += data->chunkSize; 01211 } 01212 01213 // UDP test sender thread function. 01214 PAL_PRIVATE void socketUDPBufferedTestSender(const void *arg) 01215 { 01216 palStatus_t result = PAL_SUCCESS; 01217 pal_udp_test_data_t *data = (pal_udp_test_data_t*)arg; // cast from const to non-const 01218 size_t sent = 0, totalSent = 0; 01219 01220 g_testSendBuffer = (uint8_t*)malloc(sizeof(uint8_t) * data->bufferSize); 01221 TEST_ASSERT_NOT_EQUAL(NULLPTR, g_testSendBuffer); 01222 01223 data->totalSize = 0; 01224 data->chunkSize = 0; 01225 data->currentValue = data->startValue; 01226 while (totalSent != data->messageSize) 01227 { 01228 fillUDPTestBuffer(data, g_testSendBuffer); 01229 result = pal_sendTo(g_testSockets[0], g_testSendBuffer, data->chunkSize, &(data->interfaceInfo.address), data->interfaceInfo.addressSize, &sent); 01230 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01231 totalSent += sent; 01232 pal_osDelay(5); // allow some time for the RX bits to be set 01233 }; 01234 01235 free(g_testSendBuffer); 01236 g_testSendBuffer = NULLPTR; 01237 } 01238 01239 /*! \brief Test UDP socket read in chunks 01240 * 01241 * \note The test generates data and calculates its hash, then this data is re-generated from a dedicated thread and 01242 * received on the current thread which calculates the received data hash and compares it to the original hash 01243 * 01244 * @param[in] bufSize - the read buffer size 01245 * 01246 ** \test 01247 * | # | Step | Expected | 01248 * |---|--------------------------------|-------------| 01249 * | 1 | Initialize the MD context. | PAL_SUCCESS | 01250 * | 2 | Allocate buffer. | PAL_SUCCESS | 01251 * | 3 | Generate data incrementally and update the MD context. | PAL_SUCCESS | 01252 * | 4 | Get the hash output size and validate it. | PAL_SUCCESS | 01253 * | 5 | Get the calculated hash. | PAL_SUCCESS | 01254 * | 6 | Free the MD context resources. | PAL_SUCCESS | 01255 * | 7 | Get the interface address. | PAL_SUCCESS | 01256 * | 8 | Create a (blocking) UDP socket. | PAL_SUCCESS | 01257 * | 9 | Set the socket port and set send/receive timeouts. | PAL_SUCCESS | 01258 * | 10 | Bind the socket. | PAL_SUCCESS | 01259 * | 11 | Initialize the MD context. | PAL_SUCCESS | 01260 * | 12 | Launch the data sender thread. | PAL_SUCCESS | 01261 * | 13 | Read data from the socket until there's no more data or all data has been received. | PAL_SUCCESS | 01262 * | 14 | Update the MD context. | PAL_SUCCESS | 01263 * | 15 | Terminate the sending thread. | PAL_SUCCESS | 01264 * | 16 | Close the socket. | PAL_SUCCESS | 01265 * | 17 | Get the hash output size and validate it. | PAL_SUCCESS | 01266 * | 18 | Get the calculated hash and compare it. | PAL_SUCCESS | 01267 * | 19 | Free the MD context resources. | PAL_SUCCESS | 01268 * | 20 | Free allocated buffer. | PAL_SUCCESS | 01269 */ 01270 PAL_PRIVATE void socketUDPBuffered(size_t bufSize) 01271 { 01272 palStatus_t result = PAL_SUCCESS; 01273 pal_udp_test_data_t data = { PAL_NET_TEST_BUFFERED_UDP_MESSAGE_SIZE, bufSize, 0 }; 01274 uint8_t expectedHash[PAL_SHA256_SIZE] = { 0 }, actualHash[PAL_SHA256_SIZE] = { 0 }; 01275 size_t read = 0, totalRead = 0, hashlen = 0; 01276 int timeout = 1000; 01277 palMDHandle_t handle = NULLPTR; 01278 palThreadID_t thread = NULLPTR; 01279 01280 /*#1*/ 01281 result = pal_mdInit(&handle, PAL_SHA256); 01282 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01283 TEST_ASSERT_NOT_EQUAL(NULLPTR, handle); 01284 01285 /*#2*/ 01286 g_testRecvBuffer = (uint8_t*)malloc(sizeof(uint8_t) * bufSize); 01287 TEST_ASSERT_NOT_EQUAL(NULLPTR, g_testRecvBuffer); 01288 01289 /*#3*/ 01290 data.totalSize = data.chunkSize = 0; 01291 data.currentValue = data.startValue; 01292 while (data.totalSize != data.messageSize) 01293 { 01294 fillUDPTestBuffer(&data, g_testRecvBuffer); 01295 result = pal_mdUpdate(handle, g_testRecvBuffer, data.chunkSize); 01296 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01297 }; 01298 01299 /*#4*/ 01300 result = pal_mdGetOutputSize(handle, &hashlen); 01301 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01302 TEST_ASSERT_EQUAL_HEX(PAL_SHA256_SIZE, hashlen); 01303 01304 /*#5*/ 01305 result = pal_mdFinal(handle, expectedHash); 01306 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01307 01308 /*#6*/ 01309 result = pal_mdFree(&handle); 01310 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01311 01312 /*#7*/ 01313 memset(&(data.interfaceInfo), 0, sizeof(data.interfaceInfo)); 01314 result = pal_getNetInterfaceInfo(0, &(data.interfaceInfo)); 01315 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01316 01317 /*#8*/ 01318 result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM , false, 0, &g_testSockets[0]); 01319 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01320 01321 /*#9*/ 01322 result = pal_setSockAddrPort(&(data.interfaceInfo.address), PAL_NET_TEST_BUFFERED_UDP_PORT); 01323 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01324 01325 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO , &timeout, sizeof(timeout)); 01326 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01327 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO , &timeout, sizeof(timeout)); 01328 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01329 01330 /*#10*/ 01331 result = pal_bind(g_testSockets[0], &(data.interfaceInfo.address), data.interfaceInfo.addressSize); 01332 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01333 01334 /*#11*/ 01335 handle = NULLPTR; 01336 result = pal_mdInit(&handle, PAL_SHA256); 01337 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01338 TEST_ASSERT_NOT_EQUAL(NULLPTR, handle); 01339 01340 /*#12*/ 01341 result = pal_osThreadCreateWithAlloc(socketUDPBufferedTestSender, &data, PAL_osPriorityNormal, PAL_TEST_THREAD_STACK_SIZE, NULL, &thread); 01342 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01343 TEST_ASSERT_NOT_EQUAL(NULLPTR, thread); 01344 01345 /*#13*/ 01346 do 01347 { 01348 read = 0; 01349 memset(g_testRecvBuffer, 0, data.bufferSize); 01350 result = pal_receiveFrom(g_testSockets[0], g_testRecvBuffer, data.bufferSize, &(data.interfaceInfo.address), &(data.interfaceInfo.addressSize), &read); 01351 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01352 /*#14*/ 01353 result = pal_mdUpdate(handle, g_testRecvBuffer, read); 01354 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01355 totalRead += read; 01356 } while (read > 0 && totalRead < data.messageSize); 01357 01358 /*#15*/ 01359 result = pal_osThreadTerminate(&thread); 01360 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01361 01362 /*#16*/ 01363 result = pal_close(&g_testSockets[0]); 01364 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01365 01366 /*#17*/ 01367 hashlen = 0; 01368 result = pal_mdGetOutputSize(handle, &hashlen); 01369 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01370 TEST_ASSERT_EQUAL_HEX(PAL_SHA256_SIZE, hashlen); 01371 01372 /*#18*/ 01373 result = pal_mdFinal(handle, actualHash); 01374 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01375 TEST_ASSERT_EQUAL_MEMORY(expectedHash, actualHash, PAL_SHA256_SIZE); 01376 01377 /*#19*/ 01378 result = pal_mdFree(&handle); 01379 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01380 01381 /*#20*/ 01382 free(g_testRecvBuffer); 01383 g_testRecvBuffer = NULLPTR; 01384 } 01385 01386 /*! \brief Test function UDP socket read in small chunks 01387 * 01388 ** \test 01389 */ 01390 TEST(pal_socket, socketUDPBufferedSmall) 01391 { 01392 socketUDPBuffered(PAL_NET_TEST_BUFFERED_UDP_BUF_SIZE_SMALL); 01393 } 01394 01395 /*! \brief Test function UDP socket read in large chunks 01396 * 01397 ** \test 01398 */ 01399 TEST(pal_socket, socketUDPBufferedLarge) 01400 { 01401 socketUDPBuffered(PAL_NET_TEST_BUFFERED_UDP_BUF_SIZE_LARGE); 01402 } 01403 01404 #ifdef __LINUX__ // Linux CI tests for socketTCPBufferedSmall & socketTCPBufferedLarge must use an ipv4 address in order to connect to the external host 01405 PAL_PRIVATE palStatus_t getAddressInfoIPv4(char const *url, palSocketAddress_t *address, palSocketLength_t* addressLength) 01406 { 01407 struct addrinfo *info = NULLPTR; 01408 struct addrinfo hints = { 0 }; 01409 struct sockaddr_in *sockAddress = NULLPTR; 01410 palIpV4Addr_t ipV4Address = { 0 }; 01411 int ret; 01412 palStatus_t result; 01413 01414 hints.ai_family = AF_INET; 01415 ret = getaddrinfo(url, NULL, &hints, &info); 01416 TEST_ASSERT_EQUAL(0, ret); 01417 TEST_ASSERT_NOT_EQUAL(NULLPTR, info); 01418 TEST_ASSERT_EQUAL(AF_INET, info->ai_family); 01419 01420 sockAddress = (struct sockaddr_in*)info->ai_addr; 01421 memcpy(ipV4Address, &(sockAddress->sin_addr), PAL_IPV4_ADDRESS_SIZE); 01422 freeaddrinfo(info); 01423 01424 result = pal_setSockAddrIPV4Addr(address, ipV4Address); 01425 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01426 *addressLength = sizeof(struct sockaddr_in); 01427 return result; 01428 } 01429 #endif 01430 01431 /*! \brief Test TCP socket read in chunks 01432 * 01433 * \note The test attempts to perform an HTTP get request to a google (jquery) CDN, read the file in chunks (ignoring HTTP headers) and compare its hash to a pre-known hash using SHA256. 01434 * 01435 * @param[in] bufSize - the read buffer size 01436 * 01437 ** \test 01438 * | # | Step | Expected | 01439 * |---|--------------------------------|-------------| 01440 * | 1 | Create a (blocking) TCP socket. | PAL_SUCCESS | 01441 * | 2 | Look up the IP address of the CDN server. | PAL_SUCCESS | 01442 * | 3 | Set the port to the CDN server's HTTP port and set send/receive timeouts. | PAL_SUCCESS | 01443 * | 4 | Connect the socket to the CDN server. | PAL_SUCCESS | 01444 * | 5 | Send an HTTP get request to the CDN server. | PAL_SUCCESS | 01445 * | 6 | Initialize the MD context. | PAL_SUCCESS | 01446 * | 7 | Allocate HTTP response buffer. | PAL_SUCCESS | 01447 * | 8 | Read the server's response until there's no more data to read. | PAL_SUCCESS | 01448 * | 9 | If we're done dealing with the HTTP headers then update the MD context. | PAL_SUCCESS | 01449 * | 10 | Locate the end of the HTTP headers in the server's response (HTTP headers end with a double CRLF). | PAL_SUCCESS | 01450 * | 11 | Update the MD context. | PAL_SUCCESS | 01451 * | 12 | Close the socket. | PAL_SUCCESS | 01452 * | 13 | Get the hash output size and validate it. | PAL_SUCCESS | 01453 * | 14 | Get the calculated hash and compare it to the pre-known hash. | PAL_SUCCESS | 01454 * | 15 | Free the MD context resources. | PAL_SUCCESS | 01455 * | 16 | Free HTTP response buffer. | PAL_SUCCESS | 01456 */ 01457 PAL_PRIVATE void socketTCPBuffered(size_t bufSize) 01458 { 01459 palStatus_t result = PAL_SUCCESS; 01460 palSocketAddress_t address = { 0 }; 01461 palSocketLength_t addrlen = 0; 01462 int timeout = 5000; 01463 uint8_t next = '\r', state = 0; 01464 size_t read = 0, sent = 0, hashlen = 0; 01465 bool body = false; 01466 palMDHandle_t handle = NULLPTR; 01467 uint8_t actualHash[PAL_SHA256_SIZE] = { 0 }; 01468 const uint8_t expectedHash[] = // pre-calculated jquery.js 3.2.1 SHA256 01469 { 01470 0x0d, 0x90, 0x27, 0x28, 0x9f, 0xfa, 0x5d, 0x9f, 0x6c, 0x8b, 0x4e, 0x07, 0x82, 0xbb, 0x31, 0xbb, 01471 0xff, 0x2c, 0xef, 0x5e, 0xe3, 0x70, 0x8c, 0xcb, 0xcb, 0x7a, 0x22, 0xdf, 0x91, 0x28, 0xbb, 0x21 01472 }; 01473 01474 /*#1*/ 01475 result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[0]); 01476 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01477 01478 /*#2*/ 01479 result = test_getAddressInfo(PAL_NET_TEST_GOOGLE_CDN_HOST, &address, &addrlen); 01480 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01481 01482 /*#3*/ 01483 result = pal_setSockAddrPort(&address, PAL_NET_TEST_GOOGLE_CDN_HOST_PORT); 01484 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01485 01486 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO , &timeout, sizeof(timeout)); 01487 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01488 result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO , &timeout, sizeof(timeout)); 01489 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01490 01491 /*#4*/ 01492 result = pal_connect(g_testSockets[0], &address, addrlen); 01493 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01494 01495 /*#5*/ 01496 result = pal_send(g_testSockets[0], PAL_NET_TEST_GOOGLE_CDN_REQUEST, sizeof(PAL_NET_TEST_GOOGLE_CDN_REQUEST) - 1, &sent); 01497 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01498 01499 /*#6*/ 01500 result = pal_mdInit(&handle, PAL_SHA256); 01501 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01502 TEST_ASSERT_NOT_EQUAL(NULLPTR, handle); 01503 01504 /*#7*/ 01505 g_testRecvBuffer = (uint8_t*)malloc(sizeof(uint8_t) * bufSize + 1); 01506 TEST_ASSERT_NOT_EQUAL(NULLPTR, g_testRecvBuffer); 01507 01508 /*#8*/ 01509 do 01510 { 01511 read = 0; 01512 memset(g_testRecvBuffer, 0, bufSize + 1); 01513 result = pal_recv(g_testSockets[0], g_testRecvBuffer, bufSize, &read); 01514 TEST_ASSERT_TRUE((PAL_SUCCESS == result && read > 0) || (PAL_ERR_SOCKET_CONNECTION_CLOSED == result && read == 0)); 01515 01516 /*#9*/ 01517 if (body) 01518 { 01519 result = pal_mdUpdate(handle, g_testRecvBuffer, read); 01520 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01521 continue; 01522 } 01523 01524 /*#10*/ 01525 for (size_t i = 0; i < bufSize; i++) // dealing with the HTTP headers - headers end on a double CRLF 01526 { 01527 if (g_testRecvBuffer[i] == next) 01528 { 01529 next = (next == '\r') ? '\n' : '\r'; 01530 state = state | (state + 1); 01531 if (state == 0xf) 01532 { 01533 /*#11*/ 01534 body = true; 01535 result = pal_mdUpdate(handle, (g_testRecvBuffer + i + 1), strlen(((char*)g_testRecvBuffer) + i + 1)); 01536 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01537 break; 01538 } 01539 } 01540 else if (state != 0) 01541 { 01542 next = '\r'; 01543 state = 0; 01544 } 01545 } 01546 } while (read > 0); 01547 01548 /*#12*/ 01549 result = pal_close(&g_testSockets[0]); 01550 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01551 01552 /*#13*/ 01553 result = pal_mdGetOutputSize(handle, &hashlen); 01554 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01555 TEST_ASSERT_EQUAL_HEX(PAL_SHA256_SIZE, hashlen); 01556 01557 /*#14*/ 01558 result = pal_mdFinal(handle, actualHash); 01559 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01560 TEST_ASSERT_EQUAL_MEMORY(expectedHash, actualHash, PAL_SHA256_SIZE); 01561 01562 /*#15*/ 01563 result = pal_mdFree(&handle); 01564 TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result); 01565 01566 /*#16*/ 01567 free(g_testRecvBuffer); 01568 g_testRecvBuffer = NULLPTR; 01569 } 01570 01571 /*! \brief Test function TCP socket read in small chunks 01572 * 01573 ** \test 01574 */ 01575 TEST(pal_socket, socketTCPBufferedSmall) 01576 { 01577 socketTCPBuffered(PAL_NET_TEST_BUFFERED_TCP_BUF_SIZE_SMALL); 01578 } 01579 01580 /*! \brief Test function TCP socket read in large chunks 01581 * 01582 ** \test 01583 */ 01584 TEST(pal_socket, socketTCPBufferedLarge) 01585 { 01586 socketTCPBuffered(PAL_NET_TEST_BUFFERED_TCP_BUF_SIZE_LARGE); 01587 }
Generated on Tue Jul 12 2022 16:22:10 by 1.7.2