1 /* 2 * FreeRTOS+TCP <DEVELOPMENT BRANCH> 3 * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 * 5 * SPDX-License-Identifier: MIT 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy of 8 * this software and associated documentation files (the "Software"), to deal in 9 * the Software without restriction, including without limitation the rights to 10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 * the Software, and to permit persons to whom the Software is furnished to do so, 12 * subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in all 15 * copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * http://aws.amazon.com/freertos 25 * http://www.FreeRTOS.org 26 */ 27 28 29 /** 30 * @file http_client.c 31 * @brief Implements the Domain Name System for the FreeRTOS+TCP network stack. 32 */ 33 34 /* Standard includes. */ 35 #include <stdint.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 39 /* FreeRTOS includes. */ 40 #include "FreeRTOS.h" 41 #include "task.h" 42 #include "queue.h" 43 44 /* FreeRTOS+TCP includes. */ 45 #include "FreeRTOS_IP.h" 46 #include "FreeRTOS_Sockets.h" 47 #include "FreeRTOS_DNS.h" 48 #if ( ipconfigMULTI_INTERFACE != 0 ) 49 #include "FreeRTOS_Routing.h" 50 #endif 51 52 #include "http_client_test.h" 53 54 /* Exclude the whole file if FreeRTOSIPConfig.h is configured to use UDP only. */ 55 #if ( ipconfigUSE_TCP == 1 ) 56 57 #ifndef echoNUM_HTTP_CLIENTS 58 /* The number of instances of the echo client task to create. */ 59 #define echoNUM_HTTP_CLIENTS ( 2 ) 60 #endif 61 62 #ifndef httpREMOTE_FILENAME 63 #define httpREMOTE_FILENAME "/index.html" 64 #endif 65 66 /* The echo tasks create a socket, send out a number of echo requests, listen 67 * for the echo reply, then close the socket again before starting over. This 68 * delay is used between each iteration to ensure the network does not get too 69 * congested. */ 70 #define echoLOOP_DELAY ( ( TickType_t ) 150 / portTICK_PERIOD_MS ) 71 72 /* The echo server is assumed to be on port 7, which is the standard echo 73 * protocol port. */ 74 75 #define echoECHO_PORT ( 80 ) 76 77 /* If ipconfigUSE_TCP_WIN is 1 then the Tx socket will use a buffer size set by 78 * ipconfigTCP_TX_BUF_LEN, and the Tx window size will be 79 * configECHO_CLIENT_TX_WINDOW_SIZE times the buffer size. Note 80 * ipconfigTCP_TX_BUF_LEN is set in FreeRTOSIPConfig.h as it is a standard TCP/IP 81 * stack constant, whereas configECHO_CLIENT_TX_WINDOW_SIZE is set in 82 * FreeRTOSConfig.h as it is a demo application constant. */ 83 #ifndef configECHO_CLIENT_TX_WINDOW_SIZE 84 #define configECHO_CLIENT_TX_WINDOW_SIZE 2 85 #endif 86 87 /* If ipconfigUSE_TCP_WIN is 1 then the Rx socket will use a buffer size set by 88 * ipconfigTCP_RX_BUFFER_LENGTH, and the Rx window size will be 89 * configECHO_CLIENT_RX_WINDOW_SIZE times the buffer size. Note 90 * ipconfigTCP_RX_BUFFER_LENGTH is set in FreeRTOSIPConfig.h as it is a standard TCP/IP 91 * stack constant, whereas configECHO_CLIENT_RX_WINDOW_SIZE is set in 92 * FreeRTOSConfig.h as it is a demo application constant. */ 93 #ifndef configECHO_CLIENT_RX_WINDOW_SIZE 94 #define configECHO_CLIENT_RX_WINDOW_SIZE 2 95 #endif 96 97 static uint16_t usUsePortNumber = echoECHO_PORT; 98 99 /*2404:6800:4003:c02::5e */ 100 /*66.96.149.18 */ 101 /*-----------------------------------------------------------*/ 102 103 /* 104 * Uses a socket to send data to, then receive data from, the standard echo 105 * port number 7. 106 */ 107 static void prvEchoClientTask( void * pvParameters ); 108 109 void printBuffer( const char * apBuffer, 110 int aLen, 111 int aLineLen, 112 const char * apPrefix ); 113 114 /*-----------------------------------------------------------*/ 115 116 /* Counters for each created task - for inspection only. */ 117 static uint32_t ulTxRxCycles[ echoNUM_HTTP_CLIENTS ] = { 0 }, 118 ulConnections[ echoNUM_HTTP_CLIENTS ] = { 0 }, 119 xIPVersion[ echoNUM_HTTP_CLIENTS ] = { 0 }; 120 121 static TaskHandle_t xSocketTaskHandles[ echoNUM_HTTP_CLIENTS ]; 122 123 /* When element is non-zero, the corresponding task may run. */ 124 static BaseType_t xAllowedToStart[ echoNUM_HTTP_CLIENTS ] = { 0 }; 125 126 /* Each task connects to its own host. */ 127 static char pcHostNames[ echoNUM_HTTP_CLIENTS ][ ipconfigDNS_CACHE_NAME_LENGTH ]; 128 129 /* Each task retrieves its own file. */ 130 static char pcFileNames[ echoNUM_HTTP_CLIENTS ][ ipconfigDNS_CACHE_NAME_LENGTH ]; 131 132 const char get_command[] = 133 "GET %s HTTP/1.1\x0d\x0a" 134 "Host: %s\x0d\x0a" 135 "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0\x0d\x0a" 136 "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\x0d\x0a" 137 "Accept-Language: en-US,en;q=0.5\x0d\x0a" 138 "DNT: 1\x0d\x0a" 139 "Connection: keep-alive\x0d\x0a" 140 "Upgrade-Insecure-Requests: 1\x0d\x0a" 141 "If-Modified-Since: Fri, 16 Aug 2019 05:18:19 GMT\x0d\x0a" 142 "\x0d\x0a"; 143 144 /*-----------------------------------------------------------*/ 145 vStartHTTPClientTest(uint16_t usTaskStackSize,UBaseType_t uxTaskPriority)146 void vStartHTTPClientTest( uint16_t usTaskStackSize, 147 UBaseType_t uxTaskPriority ) 148 { 149 BaseType_t x; 150 static char pcNames[ echoNUM_HTTP_CLIENTS ][ configMAX_TASK_NAME_LEN + 1 ]; 151 static BaseType_t xHasStarted = pdFALSE; 152 153 if( xHasStarted == pdFALSE ) 154 { 155 xHasStarted = pdTRUE; 156 157 /* Create the echo client tasks. */ 158 for( x = 0; x < echoNUM_HTTP_CLIENTS; x++ ) 159 { 160 snprintf( pcNames[ x ], sizeof pcNames[ x ], "Client_%ld", x ); 161 xTaskCreate( prvEchoClientTask, /* The function that implements the task. */ 162 pcNames[ x ], /* Just a text name for the task to aid debugging. */ 163 usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ 164 ( void * ) x, /* The task parameter, not used in this case. */ 165 uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ 166 &( xSocketTaskHandles[ x ] ) ); /* Remember the handle. */ 167 } 168 } 169 } 170 /*-----------------------------------------------------------*/ 171 172 /** 173 * @brief Wake-up a HTTP client task. aIndex 174 * @param[in] uxIndex: the task number ( 0 .. echoNUM_HTTP_CLIENTS-1 ). 175 * @param[in] pcHost: the name of the host from which to download index.html 176 */ wakeupHTTPClient(size_t uxIndex,const char * pcHost,const char * pcFileName,uint16_t usPortNumber,BaseType_t xIPType)177 void wakeupHTTPClient( size_t uxIndex, 178 const char * pcHost, 179 const char * pcFileName, 180 uint16_t usPortNumber, 181 BaseType_t xIPType ) 182 { 183 if( ( uxIndex < echoNUM_HTTP_CLIENTS ) && ( xSocketTaskHandles[ uxIndex ] != NULL ) ) 184 { 185 xIPVersion[ uxIndex ] = xIPType; 186 usUsePortNumber = usPortNumber; 187 snprintf( pcHostNames[ uxIndex ], sizeof pcHostNames[ uxIndex ], "%s", pcHost ); 188 189 if( ( pcFileName != NULL ) && ( pcFileName[ 0 ] != 0 ) ) 190 { 191 snprintf( pcFileNames[ uxIndex ], sizeof( pcFileNames[ uxIndex ] ), pcFileName ); 192 } 193 else 194 { 195 snprintf( pcFileNames[ uxIndex ], sizeof( pcFileNames[ uxIndex ] ), httpREMOTE_FILENAME ); 196 } 197 198 xAllowedToStart[ uxIndex ]++; 199 xTaskNotifyGive( xSocketTaskHandles[ uxIndex ] ); 200 } 201 } 202 203 /** 204 * @brief Wake-up a HTTP client task. aIndex 205 * @param[in] pvParameters: the task number as a void pointer. 206 */ prvEchoClientTask(void * pvParameters)207 static void prvEchoClientTask( void * pvParameters ) 208 { 209 Socket_t xSocket = NULL; 210 211 struct freertos_sockaddr xEchoServerAddress; 212 213 size_t uxInstance; 214 int32_t xReturned, xReceivedBytes; 215 BaseType_t lTransmitted; 216 TickType_t xTimeOnEntering; 217 218 #if ( ipconfigUSE_TCP_WIN == 1 ) 219 WinProperties_t xWinProps; 220 221 /* Fill in the buffer and window sizes that will be used by the socket. */ 222 xWinProps.lTxBufSize = ipconfigTCP_TX_BUFFER_LENGTH; 223 xWinProps.lTxWinSize = configECHO_CLIENT_TX_WINDOW_SIZE; 224 xWinProps.lRxBufSize = ipconfigTCP_RX_BUFFER_LENGTH; 225 xWinProps.lRxWinSize = configECHO_CLIENT_RX_WINDOW_SIZE; 226 #endif /* ipconfigUSE_TCP_WIN */ 227 228 #if ( ipconfigUSE_IPv6 != 0 ) 229 struct freertos_sockaddr * pxAddress = ( struct freertos_sockaddr * ) &xEchoServerAddress; 230 #else 231 struct freertos_sockaddr * pxAddress = &xEchoServerAddress; 232 #endif 233 234 /* This task can be created a number of times. Each instance is numbered 235 * to enable each instance to use a different Rx and Tx buffer. The number is 236 * passed in as the task's parameter. */ 237 { 238 /* A two-step assignment. */ 239 intptr_t uxIntPtr = ( intptr_t ) pvParameters; 240 uxInstance = ( size_t ) uxIntPtr; 241 configASSERT( uxInstance < echoNUM_HTTP_CLIENTS ); 242 } 243 244 if( uxInstance < echoNUM_HTTP_CLIENTS ) 245 { 246 xSocketTaskHandles[ uxInstance ] = xTaskGetCurrentTaskHandle(); 247 } 248 249 for( ; ; ) 250 { 251 int rc; 252 struct freertos_sockaddr xBindAddress; 253 const char * pcHostname; 254 uint32_t ulIPAddress = 0U; 255 BaseType_t xHasIPv6Address = pdFALSE; 256 char pcBuffer[ 512 ]; 257 258 /* Rx and Tx time outs are used to ensure the sockets do not wait too long for 259 * missing data. */ 260 TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 2500U ); 261 TickType_t xSendTimeOut = pdMS_TO_TICKS( 2000U ); 262 #if ( ipconfigUSE_IPv6 != 0 ) 263 IPv6_Address_t xIPAddress_IPv6; 264 #endif 265 struct freertos_sockaddr xLocalAddress; 266 #if ( ipconfigMULTI_INTERFACE != 0 ) 267 struct freertos_addrinfo * pxResult = NULL; 268 struct freertos_addrinfo xHints; 269 NetworkEndPoint_t * pxEndPoint; 270 #endif 271 272 if( xSocketValid( xSocket ) == pdTRUE ) 273 { 274 FreeRTOS_closesocket( xSocket ); 275 } 276 277 xSocket = NULL; 278 279 while( xAllowedToStart[ uxInstance ] == 0 ) 280 { 281 ulTaskNotifyTake( pdTRUE, 100 ); 282 } 283 284 xAllowedToStart[ uxInstance ] = 0; 285 286 #if ( ipconfigMULTI_INTERFACE != 0 ) 287 if( xIPVersion[ uxInstance ] != 6 ) 288 { 289 xHints.ai_family = FREERTOS_AF_INET; 290 } 291 else 292 { 293 xHints.ai_family = FREERTOS_AF_INET6; 294 } 295 #endif 296 pcHostname = pcHostNames[ uxInstance ]; 297 298 { 299 #if ( ipconfigMULTI_INTERFACE == 0 ) 300 ulIPAddress = FreeRTOS_gethostbyname( pcHostname ); 301 302 if( ulIPAddress == 0U ) 303 { 304 continue; 305 } 306 #else 307 #if ( ipconfigUSE_IPv4 != 0 ) 308 pxEndPoint = FreeRTOS_FindGateWay( ipTYPE_IPv4 ); 309 310 if( ( pxEndPoint != NULL ) && ( pxEndPoint->ipv4_settings.ulGatewayAddress != 0U ) ) 311 { 312 xARPWaitResolution( pxEndPoint->ipv4_settings.ulGatewayAddress, pdMS_TO_TICKS( 1000U ) ); 313 } 314 #endif /* ( ipconfigUSE_IPv4 != 0 ) */ 315 316 BaseType_t rc_dns = FreeRTOS_getaddrinfo( 317 pcHostname, /* The node. */ 318 NULL, /* const char *pcService: ignored for now. */ 319 &xHints, /* If not NULL: preferences. */ 320 &pxResult ); /* An allocated struct, containing the results. */ 321 FreeRTOS_printf( ( "httpTest: FreeRTOS_getaddrinfo: rc %d\n", ( int ) rc_dns ) ); 322 323 if( ( rc_dns != 0 ) || ( pxResult == NULL ) ) 324 { 325 continue; 326 } 327 328 if( pxResult->ai_family == FREERTOS_AF_INET4 ) 329 { 330 /* ulIPAddress = ( ( struct freertos_sockaddr * ) pxResult->ai_addr )->sin_address.ulIP_IPv4; */ 331 ulIPAddress = pxResult->ai_addr->sin_address.ulIP_IPv4; 332 } 333 334 #if ( ipconfigUSE_IPv6 != 0 ) 335 else if( pxResult->ai_family == FREERTOS_AF_INET6 ) 336 { 337 struct freertos_sockaddr * pxAddr6; 338 339 pxAddr6 = ( struct freertos_sockaddr * ) pxResult->ai_addr; 340 memcpy( xIPAddress_IPv6.ucBytes, pxAddr6->sin_address.xIP_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); 341 xHasIPv6Address = pdTRUE; 342 } 343 #endif 344 else 345 { 346 continue; 347 } 348 #endif /* if ( ipconfigMULTI_INTERFACE == 0 ) */ 349 } 350 351 #if ( ipconfigUSE_IPv6 != 0 ) 352 if( xHasIPv6Address != 0 ) 353 { 354 xEchoServerAddress.sin_len = sizeof( struct freertos_sockaddr ); 355 xEchoServerAddress.sin_family = FREERTOS_AF_INET6; 356 xEchoServerAddress.sin_port = FreeRTOS_htons( usUsePortNumber ); 357 memcpy( xEchoServerAddress.sin_address.xIP_IPv6.ucBytes, xIPAddress_IPv6.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); 358 } 359 else 360 #endif 361 362 if( ulIPAddress != 0U ) 363 { 364 pxAddress->sin_len = sizeof( struct freertos_sockaddr ); 365 pxAddress->sin_family = FREERTOS_AF_INET; 366 pxAddress->sin_port = FreeRTOS_htons( usUsePortNumber ); 367 pxAddress->sin_address.ulIP_IPv4 = ulIPAddress; 368 } 369 else 370 { 371 configASSERT( 0 == 1 ); 372 } 373 374 /* Create a TCP socket. */ 375 xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP ); 376 configASSERT( xSocketValid( xSocket ) == pdTRUE ); 377 378 memset( &( xBindAddress ), 0, sizeof( xBindAddress ) ); 379 380 #if ( ipconfigMULTI_INTERFACE != 0 ) 381 #if ( ipconfigUSE_IPv6 != 0 ) 382 if( xEchoServerAddress.sin_family == FREERTOS_AF_INET6 ) 383 { 384 pxEndPoint = FreeRTOS_FindEndPointOnNetMask_IPv6( &( xEchoServerAddress.sin_address.xIP_IPv6 ) ); 385 386 if( pxEndPoint == NULL ) 387 { 388 pxEndPoint = FreeRTOS_FindGateWay( ipTYPE_IPv6 ); 389 } 390 391 if( pxEndPoint != NULL ) 392 { 393 /*memcpy( xEchoServerAddress.sin_address.xIP_IPv6.ucBytes, pxEndPoint->ipv6.xIPAddress.ucBytes, ipSIZE_OF_IPv6_ADDRESS ); */ 394 } 395 } 396 else 397 #endif /* if ( ipconfigUSE_IPv6 != 0 ) */ 398 { 399 pxEndPoint = FreeRTOS_FindEndPointOnNetMask( pxAddress->sin_address.ulIP_IPv4, 9999 ); 400 401 if( pxEndPoint != NULL ) 402 { 403 xBindAddress.sin_address.ulIP_IPv4 = pxEndPoint->ipv4_settings.ulIPAddress; 404 xBindAddress.sin_family = FREERTOS_AF_INET; 405 } 406 } 407 #endif /* if ( ipconfigMULTI_INTERFACE != 0 ) */ 408 rc = FreeRTOS_bind( xSocket, &( xBindAddress ), sizeof( xBindAddress ) ); 409 410 if( rc != 0 ) 411 { 412 FreeRTOS_printf( ( "httpTest: bind fails with errno %d\n", rc ) ); 413 configASSERT( rc == 0 ); 414 } 415 416 /* Set a time out so a missing reply does not cause the task to block 417 * indefinitely. */ 418 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); 419 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) ); 420 421 #if ( ipconfigUSE_TCP_WIN == 1 ) 422 { 423 /* Set the window and buffer sizes. */ 424 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &xWinProps, sizeof( xWinProps ) ); 425 } 426 #endif /* ipconfigUSE_TCP_WIN */ 427 428 FreeRTOS_GetLocalAddress( xSocket, &xLocalAddress ); 429 /* Connect to the echo server. */ 430 rc = FreeRTOS_connect( xSocket, ( struct freertos_sockaddr * ) &xEchoServerAddress, sizeof( xEchoServerAddress ) ); 431 432 #if ( ipconfigUSE_IPv6 != 0 ) 433 struct freertos_sockaddr * pxLocalAddress = ( struct freertos_sockaddr * ) &xLocalAddress; 434 #else 435 struct freertos_sockaddr * pxLocalAddress = &xLocalAddress; 436 #endif 437 438 #if ( ipconfigUSE_IPv6 != 0 ) 439 if( pxAddress->sin_family == FREERTOS_AF_INET6 ) 440 { 441 FreeRTOS_printf( ( "httpTest: FreeRTOS_connect to %pip port %u: rc %d\n", 442 xEchoServerAddress.sin_address.xIP_IPv6.ucBytes, 443 FreeRTOS_ntohs( pxAddress->sin_port ), 444 rc ) ); 445 } 446 else 447 #endif 448 { 449 FreeRTOS_printf( ( "httpTest: FreeRTOS_connect from %lxip port %u to %lxip port %u: rc %d\n", 450 FreeRTOS_ntohl( pxLocalAddress->sin_address.ulIP_IPv4 ), 451 FreeRTOS_ntohs( pxLocalAddress->sin_port ), 452 FreeRTOS_ntohl( pxAddress->sin_address.ulIP_IPv4 ), 453 FreeRTOS_ntohs( pxAddress->sin_port ), 454 rc ) ); 455 } 456 457 if( rc == 0 ) 458 { 459 ulConnections[ uxInstance ]++; 460 461 /* Send a HTTP request. */ 462 { 463 BaseType_t xLoop; 464 size_t uxLength; 465 /* Send the string to the socket. */ 466 uxLength = snprintf( pcBuffer, sizeof( pcBuffer ), get_command, pcFileNames[ uxInstance ], pcHostname ); 467 lTransmitted = FreeRTOS_send( xSocket, /* The socket being sent to. */ 468 ( void * ) pcBuffer, /* The data being sent. */ 469 uxLength, /* The length of the data being sent. */ 470 0 ); /* No flags. */ 471 FreeRTOS_printf( ( "httpTest: FreeRTOS_send : rc %ld\n", lTransmitted ) ); 472 473 if( lTransmitted < 0 ) 474 { 475 /* Error? */ 476 break; 477 } 478 479 /* Clear the buffer into which the echoed string will be 480 * placed. */ 481 memset( ( void * ) pcBuffer, 0x00, sizeof( pcBuffer ) ); 482 xReceivedBytes = 0; 483 484 /* Receive data echoed back to the socket. */ 485 for( xLoop = 0; xLoop < 10; xLoop++ ) 486 { 487 xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */ 488 pcBuffer, /* The buffer into which the received data will be written. */ 489 sizeof( pcBuffer ), /* The size of the buffer provided to receive the data. */ 490 0 ); /* No flags. */ 491 492 FreeRTOS_printf( ( "httpTest: FreeRTOS_recv : rc %ld\n", xReturned ) ); 493 494 if( xReturned < 0 ) 495 { 496 /* Error occurred. Latch it so it can be detected 497 * below. */ 498 xReceivedBytes = xReturned; 499 break; 500 } 501 else if( xReturned == 0 ) 502 { 503 /* Timed out. */ 504 break; 505 } 506 else 507 { 508 /* Use a short RX time-out the next time. */ 509 xReceiveTimeOut = pdMS_TO_TICKS( 500U ); 510 FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); 511 /* Keep a count of the bytes received so far. */ 512 xReceivedBytes += xReturned; 513 printBuffer( pcBuffer, xReturned, 129, "" ); 514 } 515 } /* for( xLoop = 0; xLoop < 10; xLoop++ ) */ 516 } 517 518 /* Finished using the connected socket, initiate a graceful close: 519 * FIN, FIN+ACK, ACK. */ 520 FreeRTOS_printf( ( "httpTest: prvEchoClientTask: shut down connection\n" ) ); 521 FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR ); 522 523 /* Expect FreeRTOS_recv() to return an error once the shutdown is 524 * complete. */ 525 xTimeOnEntering = xTaskGetTickCount(); 526 527 do 528 { 529 xReturned = FreeRTOS_recv( xSocket, /* The socket being received from. */ 530 pcBuffer, /* The buffer into which the received data will be written. */ 531 sizeof( pcBuffer ), /* The size of the buffer provided to receive the data. */ 532 0 ); 533 534 if( xReturned < 0 ) 535 { 536 break; 537 } 538 } while( ( xTaskGetTickCount() - xTimeOnEntering ) < xReceiveTimeOut ); 539 540 FreeRTOS_printf( ( "httpTest: connection is down\n" ) ); 541 } 542 543 /* Close this socket before looping back to create another. */ 544 FreeRTOS_closesocket( xSocket ); 545 xSocket = NULL; 546 FreeRTOS_printf( ( "httpTest: test is ready\n" ) ); 547 548 /* Pause for a short while to ensure the network is not too 549 * congested. */ 550 /* vTaskDelay( echoLOOP_DELAY ); */ 551 } 552 } 553 /*-----------------------------------------------------------*/ 554 printBuffer(const char * apBuffer,int aLen,int aLineLen,const char * apPrefix)555 void printBuffer( const char * apBuffer, 556 int aLen, 557 int aLineLen, 558 const char * apPrefix ) 559 { 560 const char * ptr = apBuffer; 561 const char * end = apBuffer + aLen; 562 563 for( ; ; ) 564 { 565 const char * next = ptr; 566 const char * eot; 567 568 /* Find the first null, newline of end of text. */ 569 for( ; ; ) 570 { 571 if( ( next >= end ) || ( *next == '\0' ) ) 572 { 573 eot = next; 574 next = NULL; 575 break; 576 } 577 578 if( ( *next == '\n' ) || ( *next == '\r' ) ) 579 { 580 char eol = *next == '\n' ? '\r' : '\n'; 581 eot = next; 582 583 do 584 { 585 next++; 586 } while( *next == eol ); 587 588 break; 589 } 590 591 if( ( int ) ( next - ptr ) >= aLineLen ) 592 { 593 eot = next; 594 break; 595 } 596 597 next++; 598 } 599 600 { 601 char save = *eot; 602 *( ( char * ) eot ) = '\0'; 603 FreeRTOS_printf( ( "%s%s\n", apPrefix, ptr ) ); 604 *( ( char * ) eot ) = save; 605 } 606 607 if( next == NULL ) 608 { 609 break; 610 } 611 612 ptr = next; 613 } 614 } 615 616 #endif /* ipconfigUSE_TCP */ 617