Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pal_socket_test.c Source File

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 }