static void prvTcpInit( xTcpServer_t *pxTcpServer ) { struct freertos_sockaddr addr; BaseType_t xReceiveTimeOut = 0; BaseType_t xSendTimeOut = 0; pxTcpServer->pxSendData = ( SSimpleBuf * )pvPortMalloc( sizeof( *pxTcpServer->pxSendData ) - sizeof( pxTcpServer->pxSendData->array ) + SEND_BUFFER_SIZE + 1 ); configASSERT( pxTcpServer->pxSendData != NULL ); memset( pxTcpServer->pxSendData, '\0', sizeof( *pxTcpServer->pxSendData ) ); pxTcpServer->pxSendData->LENGTH = SEND_BUFFER_SIZE + 1; FreeRTOS_GetRemoteAddress( pxTcpServer->xSocket, &addr ); FreeRTOS_debug_printf( ( "prvTcpInit: serving %xip:%u\n", FreeRTOS_ntohl( addr.sin_addr ), addr.sin_port) ); FreeRTOS_setsockopt( pxTcpServer->xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); FreeRTOS_setsockopt( pxTcpServer->xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xReceiveTimeOut ) ); }
static portBASE_TYPE prvProcessDHCPReplies( uint8_t ucExpectedMessageType, xMACAddress_t *pxMACAddress, xNetworkAddressingParameters_t *pxNetworkAddressing ) { uint8_t *pucUDPPayload, *pucLastByte; struct freertos_sockaddr xClient; uint32_t xClientLength = sizeof( xClient ); int32_t lBytes; xDHCPMessage_t *pxDHCPMessage; uint8_t *pucByte, ucOptionCode, ucLength; uint32_t ulProcessed; portBASE_TYPE xReturn = pdFALSE; const uint32_t ulMandatoryOptions = 2; /* DHCP server address, and the correct DHCP message type must be present in the options. */ lBytes = FreeRTOS_recvfrom( xDHCPSocket, ( void * ) &pucUDPPayload, 0, FREERTOS_ZERO_COPY, &xClient, &xClientLength ); if( lBytes > 0 ) { /* Map a DHCP structure onto the received data. */ pxDHCPMessage = ( xDHCPMessage_t * ) ( pucUDPPayload ); /* Sanity check. */ if( ( pxDHCPMessage->ulDHCPCookie == dhcpCOOKIE ) && ( pxDHCPMessage->ucOpcode == dhcpREPLY_OPCODE ) && ( pxDHCPMessage->ulTransactionID == ulTransactionId ) ) { if( memcmp( ( void * ) &( pxDHCPMessage->ucClientHardwareAddress ), ( void * ) pxMACAddress, sizeof( xMACAddress_t ) ) == 0 ) { /* None of the essential options have been processed yet. */ ulProcessed = 0; /* Walk through the options until the dhcpOPTION_END_BYTE byte is found, taking care not to walk off the end of the options. */ pucByte = &( pxDHCPMessage->ucFirstOptionByte ); pucLastByte = &( pucUDPPayload[ lBytes - dhcpMAX_OPTION_LENGTH_OF_INTEREST ] ); while( ( *pucByte != dhcpOPTION_END_BYTE ) && ( pucByte < pucLastByte ) ) { ucOptionCode = *pucByte; pucByte++; ucLength = *pucByte; pucByte++; switch( ucOptionCode ) { case dhcpMESSAGE_TYPE_OPTION_CODE : if( *pucByte == ucExpectedMessageType ) { /* The message type is the message type the state machine is expecting. */ ulProcessed++; } else if( *pucByte == dhcpMESSAGE_TYPE_NACK ) { if( ucExpectedMessageType == dhcpMESSAGE_TYPE_ACK ) { /* Start again. */ eDHCPState = eWaitingSendFirstDiscover; } } else { /* Don't process other message types. */ } break; case dhcpSUBNET_MASK_OPTION_CODE : if( ucLength == sizeof( uint32_t ) ) { memcpy( ( void * ) &( pxNetworkAddressing->ulNetMask ), ( void * ) pucByte, ( size_t ) ucLength ); } break; case dhcpGATEWAY_OPTION_CODE : if( ucLength == sizeof( uint32_t ) ) { /* ulProcessed is not incremented in this case because the gateway is not essential. */ memcpy( ( void * ) &( pxNetworkAddressing->ulGatewayAddress ), ( void * ) pucByte, ( size_t ) ucLength ); } break; case hdcpDNS_SERVER_OPTIONS_CODE : /* ulProcessed is not incremented in this case because the DNS server is not essential. Only the first DNS server address is taken. */ memcpy( ( void * ) &( pxNetworkAddressing->ulDNSServerAddress ), ( void * ) pucByte, sizeof( uint32_t ) ); break; case dhcpSERVER_IP_ADDRESS_OPTION_CODE : if( ucLength == sizeof( uint32_t ) ) { if( ucExpectedMessageType == dhcpMESSAGE_TYPE_OFFER ) { /* Offers state the replying server. */ ulProcessed++; memcpy( ( void * ) &ulDHCPServerAddress, ( void * ) pucByte, ( size_t ) ucLength ); } else { /* The ack must come from the expected server. */ if( memcmp( ( void * ) &ulDHCPServerAddress, ( void * ) pucByte, ( size_t ) ucLength ) == 0 ) { ulProcessed++; } } } break; case dhcpLEASE_TIME_OPTION_CODE : if( ucLength == sizeof( &ulLeaseTime ) ) { /* ulProcessed is not incremented in this case because the lease time is not essential. */ memcpy( ( void * ) &ulLeaseTime, ( void * ) pucByte, ( size_t ) ucLength ); ulLeaseTime = FreeRTOS_ntohl( ulLeaseTime ); /* Convert the lease time to milliseconds (*1000) then ticks (/portTICK_RATE_MS). */ ulLeaseTime *= ( 1000UL / portTICK_RATE_MS ); /* Divide the lease time to ensure a renew request is sent before the lease actually expires. */ ulLeaseTime >>= 1UL; } break; default : /* Not interested in this field. */ break; } /* Jump over the data to find the next option code. */ if( ucLength == 0 ) { break; } else { pucByte += ucLength; } } /* Were all the mandatory options received? */ if( ulProcessed == ulMandatoryOptions ) { ulOfferedIPAddress = pxDHCPMessage->ulYourIPAddress_yiaddr; xReturn = pdPASS; } }
static void prvTreatNBNS( uint8_t *pucUDPPayloadBuffer, uint32_t ulIPAddress ) { uint16_t usFlags, usType, usClass; uint8_t *pucSource, *pucTarget; uint8_t ucByte; uint8_t ucNBNSName[ 17 ]; usFlags = usChar2u16( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usFlags ) ); if( ( usFlags & dnsNBNS_FLAGS_OPCODE_MASK ) == dnsNBNS_FLAGS_OPCODE_QUERY ) { usType = usChar2u16( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usType ) ); usClass = usChar2u16( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usClass ) ); /* Not used for now */ ( void )usClass; /* For NBNS a name is 16 bytes long, written with capitals only. Make sure that the copy is terminated with a zero. */ pucTarget = ucNBNSName + sizeof(ucNBNSName ) - 2; pucTarget[ 1 ] = '\0'; /* Start with decoding the last 2 bytes. */ pucSource = pucUDPPayloadBuffer + ( offsetof( NBNSRequest_t, ucName ) + ( dnsNBNS_ENCODED_NAME_LENGTH - 2 ) ); for( ;; ) { ucByte = ( uint8_t ) ( ( ( pucSource[ 0 ] - 0x41 ) << 4 ) | ( pucSource[ 1 ] - 0x41 ) ); /* Make sure there are no trailing spaces in the name. */ if( ( ucByte == ' ' ) && ( pucTarget[ 1 ] == '\0' ) ) { ucByte = '\0'; } *pucTarget = ucByte; if( pucTarget == ucNBNSName ) { break; } pucTarget -= 1; pucSource -= 2; } #if( ipconfigUSE_DNS_CACHE == 1 ) { if( ( usFlags & dnsNBNS_FLAGS_RESPONSE ) != 0 ) { /* If this is a response from another device, add the name to the DNS cache */ prvProcessDNSCache( ( char * ) ucNBNSName, &ulIPAddress, pdFALSE ); } } #else { /* Avoid compiler warnings. */ ( void ) ulIPAddress; } #endif /* ipconfigUSE_DNS_CACHE */ if( ( ( usFlags & dnsNBNS_FLAGS_RESPONSE ) == 0 ) && ( usType == dnsNBNS_TYPE_NET_BIOS ) && ( xApplicationDNSQueryHook( ( const char * ) ucNBNSName ) != pdFALSE ) ) { uint16_t usLength; DNSMessage_t *pxMessage; NBNSAnswer_t *pxAnswer; /* Someone is looking for a device with ucNBNSName, prepare a positive reply. */ NetworkBufferDescriptor_t *pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer ); if( ( xBufferAllocFixedSize == pdFALSE ) && ( pxNetworkBuffer != NULL ) ) { NetworkBufferDescriptor_t *pxNewBuffer; BaseType_t xDataLength = pxNetworkBuffer->xDataLength + sizeof( UDPHeader_t ) + sizeof( EthernetHeader_t ) + sizeof( IPHeader_t ); /* The field xDataLength was set to the length of the UDP payload. The answer (reply) will be longer than the request, so the packet must be duplicated into a bigger buffer */ pxNetworkBuffer->xDataLength = xDataLength; pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, xDataLength + 16 ); if( pxNewBuffer != NULL ) { pucUDPPayloadBuffer = pxNewBuffer->pucEthernetBuffer + sizeof( UDPPacket_t ); pxNetworkBuffer = pxNewBuffer; } else { /* Just prevent that a reply will be sent */ pxNetworkBuffer = NULL; } } /* Should not occur: pucUDPPayloadBuffer is part of a xNetworkBufferDescriptor */ if( pxNetworkBuffer != NULL ) { pxMessage = (DNSMessage_t *)pucUDPPayloadBuffer; /* As the fields in the structures are not word-aligned, we have to copy the values byte-by-byte using macro's vSetField16() and vSetField32() */ vSetField16( pxMessage, DNSMessage_t, usFlags, dnsNBNS_QUERY_RESPONSE_FLAGS ); /* 0x8500 */ vSetField16( pxMessage, DNSMessage_t, usQuestions, 0 ); vSetField16( pxMessage, DNSMessage_t, usAnswers, 1 ); vSetField16( pxMessage, DNSMessage_t, usAuthorityRRs, 0 ); vSetField16( pxMessage, DNSMessage_t, usAdditionalRRs, 0 ); pxAnswer = (NBNSAnswer_t *)( pucUDPPayloadBuffer + offsetof( NBNSRequest_t, usType ) ); vSetField16( pxAnswer, NBNSAnswer_t, usType, usType ); /* Type */ vSetField16( pxAnswer, NBNSAnswer_t, usClass, dnsNBNS_CLASS_IN ); /* Class */ vSetField32( pxAnswer, NBNSAnswer_t, ulTTL, dnsNBNS_TTL_VALUE ); vSetField16( pxAnswer, NBNSAnswer_t, usDataLength, 6 ); /* 6 bytes including the length field */ vSetField16( pxAnswer, NBNSAnswer_t, usNbFlags, dnsNBNS_NAME_FLAGS ); vSetField32( pxAnswer, NBNSAnswer_t, ulIPAddress, FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) ); usLength = ( uint16_t ) ( offsetof( NBNSRequest_t, usType ) + sizeof( NBNSAnswer_t ) ); prvReplyDNSMessage( pxNetworkBuffer, usLength ); } } } }
static uint32_t prvParseDNSReply( uint8_t *pucUDPPayloadBuffer, TickType_t xIdentifier ) { DNSMessage_t *pxDNSMessageHeader; uint32_t ulIPAddress = 0UL; #if( ipconfigUSE_LLMNR == 1 ) char *pcRequestedName = NULL; #endif uint8_t *pucByte; uint16_t x, usDataLength, usQuestions; #if( ipconfigUSE_LLMNR == 1 ) uint16_t usType = 0, usClass = 0; #endif #if( ipconfigUSE_DNS_CACHE == 1 ) char pcName[128] = ""; /*_RB_ What is the significance of 128? Probably too big to go on the stack for a small MCU but don't know how else it could be made re-entrant. Might be necessary. */ #endif pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer; if( pxDNSMessageHeader->usIdentifier == ( uint16_t ) xIdentifier ) { /* Start at the first byte after the header. */ pucByte = pucUDPPayloadBuffer + sizeof( DNSMessage_t ); /* Skip any question records. */ usQuestions = FreeRTOS_ntohs( pxDNSMessageHeader->usQuestions ); for( x = 0; x < usQuestions; x++ ) { #if( ipconfigUSE_LLMNR == 1 ) { if( x == 0 ) { pcRequestedName = ( char * ) pucByte; } } #endif #if( ipconfigUSE_DNS_CACHE == 1 ) if( x == 0 ) { pucByte = prvReadNameField( pucByte, pcName, sizeof( pcName ) ); } else #endif /* ipconfigUSE_DNS_CACHE */ { /* Skip the variable length pcName field. */ pucByte = prvSkipNameField( pucByte ); } #if( ipconfigUSE_LLMNR == 1 ) { /* usChar2u16 returns value in host endianness. */ usType = usChar2u16( pucByte ); usClass = usChar2u16( pucByte + 2 ); } #endif /* ipconfigUSE_LLMNR */ /* Skip the type and class fields. */ pucByte += sizeof( uint32_t ); } /* Search through the answers records. */ pxDNSMessageHeader->usAnswers = FreeRTOS_ntohs( pxDNSMessageHeader->usAnswers ); if( ( pxDNSMessageHeader->usFlags & dnsRX_FLAGS_MASK ) == dnsEXPECTED_RX_FLAGS ) { for( x = 0; x < pxDNSMessageHeader->usAnswers; x++ ) { pucByte = prvSkipNameField( pucByte ); /* Is the type field that of an A record? */ if( usChar2u16( pucByte ) == dnsTYPE_A_HOST ) { /* This is the required record. Skip the type, class, and time to live fields, plus the first byte of the data length. */ pucByte += ( sizeof( uint32_t ) + sizeof( uint32_t ) + sizeof( uint8_t ) ); /* Sanity check the data length. */ if( ( size_t ) *pucByte == sizeof( uint32_t ) ) { /* Skip the second byte of the length. */ pucByte++; /* Copy the IP address out of the record. */ memcpy( ( void * ) &ulIPAddress, ( void * ) pucByte, sizeof( uint32_t ) ); #if( ipconfigUSE_DNS_CACHE == 1 ) { prvProcessDNSCache( pcName, &ulIPAddress, pdFALSE ); } #endif /* ipconfigUSE_DNS_CACHE */ #if( ipconfigDNS_USE_CALLBACKS != 0 ) { /* See if any asynchronous call was made to FreeRTOS_gethostbyname_a() */ vDNSDoCallback( ( TickType_t ) pxDNSMessageHeader->usIdentifier, pcName, ulIPAddress ); } #endif /* ipconfigDNS_USE_CALLBACKS != 0 */ } break; } else { /* Skip the type, class and time to live fields. */ pucByte += ( sizeof( uint32_t ) + sizeof( uint32_t ) ); /* Determine the length of the data in the field. */ memcpy( ( void * ) &usDataLength, ( void * ) pucByte, sizeof( uint16_t ) ); usDataLength = FreeRTOS_ntohs( usDataLength ); /* Jump over the data length bytes, and the data itself. */ pucByte += usDataLength + sizeof( uint16_t ); } } } #if( ipconfigUSE_LLMNR == 1 ) else if( ( usQuestions != ( uint16_t )0u ) && ( usType == ( uint16_t )dnsTYPE_A_HOST ) && ( usClass == ( uint16_t )dnsCLASS_IN ) ) { /* If this is not a reply to our DNS request, it might an LLMNR request. */ if( xApplicationDNSQueryHook ( ( pcRequestedName + 1 ) ) ) { int16_t usLength; NetworkBufferDescriptor_t *pxNewBuffer = NULL; NetworkBufferDescriptor_t *pxNetworkBuffer = pxUDPPayloadBuffer_to_NetworkBuffer( pucUDPPayloadBuffer ); LLMNRAnswer_t *pxAnswer; if( ( xBufferAllocFixedSize == pdFALSE ) && ( pxNetworkBuffer != NULL ) ) { BaseType_t xDataLength = pxNetworkBuffer->xDataLength + sizeof( UDPHeader_t ) + sizeof( EthernetHeader_t ) + sizeof( IPHeader_t ); /* The field xDataLength was set to the length of the UDP payload. The answer (reply) will be longer than the request, so the packet must be duplicaed into a bigger buffer */ pxNetworkBuffer->xDataLength = xDataLength; pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, xDataLength + 16 ); if( pxNewBuffer != NULL ) { BaseType_t xOffset1, xOffset2; xOffset1 = ( BaseType_t ) ( pucByte - pucUDPPayloadBuffer ); xOffset2 = ( BaseType_t ) ( ( ( uint8_t * ) pcRequestedName ) - pucUDPPayloadBuffer ); pxNetworkBuffer = pxNewBuffer; pucUDPPayloadBuffer = pxNetworkBuffer->pucEthernetBuffer + ipUDP_PAYLOAD_OFFSET_IPv4; pucByte = pucUDPPayloadBuffer + xOffset1; pcRequestedName = ( char * ) ( pucUDPPayloadBuffer + xOffset2 ); pxDNSMessageHeader = ( DNSMessage_t * ) pucUDPPayloadBuffer; } else { /* Just to indicate that the message may not be answered. */ pxNetworkBuffer = NULL; } } if( pxNetworkBuffer != NULL ) { pxAnswer = (LLMNRAnswer_t *)pucByte; /* Leave 'usIdentifier' and 'usQuestions' untouched. */ vSetField16( pxDNSMessageHeader, DNSMessage_t, usFlags, dnsLLMNR_FLAGS_IS_REPONSE ); /* Set the response flag */ vSetField16( pxDNSMessageHeader, DNSMessage_t, usAnswers, 1 ); /* Provide a single answer */ vSetField16( pxDNSMessageHeader, DNSMessage_t, usAuthorityRRs, 0 ); /* No authority */ vSetField16( pxDNSMessageHeader, DNSMessage_t, usAdditionalRRs, 0 ); /* No additional info */ pxAnswer->ucNameCode = dnsNAME_IS_OFFSET; pxAnswer->ucNameOffset = ( uint8_t )( pcRequestedName - ( char * ) pucUDPPayloadBuffer ); vSetField16( pxAnswer, LLMNRAnswer_t, usType, dnsTYPE_A_HOST ); /* Type A: host */ vSetField16( pxAnswer, LLMNRAnswer_t, usClass, dnsCLASS_IN ); /* 1: Class IN */ vSetField32( pxAnswer, LLMNRAnswer_t, ulTTL, dnsLLMNR_TTL_VALUE ); vSetField16( pxAnswer, LLMNRAnswer_t, usDataLength, 4 ); vSetField32( pxAnswer, LLMNRAnswer_t, ulIPAddress, FreeRTOS_ntohl( *ipLOCAL_IP_ADDRESS_POINTER ) ); usLength = ( int16_t ) ( sizeof( *pxAnswer ) + ( size_t ) ( pucByte - pucUDPPayloadBuffer ) ); prvReplyDNSMessage( pxNetworkBuffer, usLength ); if( pxNewBuffer != NULL ) { vReleaseNetworkBufferAndDescriptor( pxNewBuffer ); } } } } #endif /* ipconfigUSE_LLMNR == 1 */ } return ulIPAddress; }
static void prvProcessDNSCache( const char *pcName, uint32_t *pulIP, BaseType_t xLookUp ) { BaseType_t x; BaseType_t xFound = pdFALSE; static BaseType_t xFreeEntry = 0; /* For each entry in the DNS cache table. */ for( x = 0; x < ipconfigDNS_CACHE_ENTRIES; x++ ) { if( xDNSCache[ x ].pcName[ 0 ] == 0 ) { break; } if( strncmp( xDNSCache[ x ].pcName, pcName, sizeof( xDNSCache[ x ].pcName ) ) == 0 ) { /* Is this function called for a lookup or to add/update an IP address? */ if( xLookUp != pdFALSE ) { *pulIP = xDNSCache[ x ].ulIPAddress; } else { xDNSCache[ x ].ulIPAddress = *pulIP; } xFound = pdTRUE; break; } } if( xFound == pdFALSE ) { if( xLookUp != pdFALSE ) { *pulIP = 0; } else { /* Called to add or update an item */ strncpy( xDNSCache[ xFreeEntry ].pcName, pcName, sizeof( xDNSCache[ xFreeEntry ].pcName ) ); xDNSCache[ xFreeEntry ].ulIPAddress = *pulIP; xFreeEntry++; if( xFreeEntry == ipconfigDNS_CACHE_ENTRIES ) { xFreeEntry = 0; } } } if( ( xLookUp == 0 ) || ( *pulIP != 0 ) ) { FreeRTOS_debug_printf( ( "prvProcessDNSCache: %s: '%s' @ %lxip\n", xLookUp ? "look-up" : "add", pcName, FreeRTOS_ntohl( *pulIP ) ) ); } }
static void prvConnectionListeningTask( void *pvParameters ) { struct freertos_sockaddr xClient, xBindAddress; xSocket_t xListeningSocket; socklen_t xSize = sizeof( xClient ); static const TickType_t xReceiveTimeOut = 0; //portMAX_DELAY; const BaseType_t xBacklog = 10; xSocketSet_t xSocketSet; struct xTCP_SERVER *pxServerList = NULL; struct xTCP_SERVER *pxIterator; xWinProperties_t winProps; /* Just to prevent compiler warnings. */ ( void ) pvParameters; /* Attempt to open the socket. */ xListeningSocket = FreeRTOS_socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ); configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET ); /* Set a time out so accept() will just wait for a connection. */ FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); memset(&winProps, '\0', sizeof( winProps ) ); // Size in units of MSS winProps.lTxBufSize = 1 * 1460;//1000; winProps.lTxWinSize = 2; winProps.lRxBufSize = 2 * 1460; winProps.lRxWinSize = 2; FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_WIN_PROPERTIES, ( void * ) &winProps, sizeof( winProps ) ); /* The strange casting is to remove compiler errors. */ xBindAddress.sin_port = ( uint16_t ) ( ( uint32_t ) pvParameters ) & 0xffffUL; xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port ); /* Bind the socket to the port that the client task will send to, then listen for incoming connections. */ while( FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) ) != 0 ); FreeRTOS_listen( xListeningSocket, xBacklog ); lastTickTime = xTaskGetTickCount (); pxServerList = NULL; xSocketSet = FreeRTOS_createsocketset( ); configASSERT( xSocketSet != NULL ); FreeRTOS_FD_SET( xListeningSocket, xSocketSet, eSELECT_READ ); for( ;; ) { TickType_t xMask = FreeRTOS_select( xSocketSet, 3000 ); if( FreeRTOS_FD_ISSET( xListeningSocket, xSocketSet ) ) { xSocket_t xNewSocket; xNewSocket = FreeRTOS_accept( xListeningSocket, &xClient, &xSize ); if ( xNewSocket && xNewSocket != FREERTOS_INVALID_SOCKET ) { xTcpServer_t *pxServer; FreeRTOS_debug_printf( ( "prvConnectionListeningTask: new connection %xip:%u\n", FreeRTOS_ntohl( xClient.sin_addr ), FreeRTOS_ntohs( xClient.sin_port ) ) ); pxServer = (xTcpServer_t *)pvPortMalloc( sizeof( *pxServer ) ); memset( pxServer, '\0', sizeof( *pxServer )); pxServer->xSocket = xNewSocket; FreeRTOS_FD_SET( xNewSocket, xSocketSet, eSELECT_READ | eSELECT_EXCEPT ); if( pxServerList == NULL ) { /* This is the first server */ pxServerList = pxServer; } else { /* Attach it to the end of the list */ for( pxIterator = pxServerList; pxIterator->pxNext != NULL; pxIterator = pxIterator->pxNext ) { } pxIterator->pxNext = pxServer; } prvTcpInit( pxServer ); } } { xTcpServer_t *pxThisServer = NULL; for( pxIterator = pxServerList; pxIterator != NULL; ) { BaseType_t rc; pxThisServer = pxIterator; /* Move to the next one before the current gets deleted */ pxIterator = pxIterator->pxNext; if( FreeRTOS_FD_ISSET( pxThisServer->xSocket, xSocketSet ) == 0 ) { continue; } rc = prvTcpWork( pxThisServer ); if( rc < 0) { FreeRTOS_FD_CLR( pxThisServer->xSocket, xSocketSet, eSELECT_ALL ); if( pxServerList = pxThisServer ) { pxServerList = pxThisServer->pxNext; } else { struct xTCP_SERVER *pxOther; for( pxOther = pxServerList; pxOther->pxNext != NULL; pxOther = pxOther->pxNext ) { if( pxOther->pxNext == pxThisServer ) { pxOther->pxNext == pxThisServer->pxNext; break; } } } /* Close the socket and free the space */ prvTcpClose( pxThisServer ); } else { pxThisServer->bHasSendRequest = prvTcpHasSendData( pxThisServer ); if( pxThisServer->bHasSendRequest ) FreeRTOS_FD_SET( pxThisServer->xSocket, xSocketSet, eSELECT_WRITE ); else FreeRTOS_FD_CLR( pxThisServer->xSocket, xSocketSet, eSELECT_WRITE ); //FreeRTOS_debug_printf( ( "SET_FD WRITE %d\n", pxServerFound->bHasSendRequest != 0 ) ); } } } if( ( xTaskGetTickCount () - lastTickTime ) > 30000 ) { lastTickTime = xTaskGetTickCount (); //plusPrintf( "ListeningTask %ld,%ld tasks\n", xTaskCount, xConfirmedCount ); } } }
static void SNTP_thread(void* pvp) { struct sntp_c params; const TickType_t xReceiveTimeOut = 500; uint32_t ntp_addr=0; struct sntp_msg sntpmsg,sntpresponse; uint16_t usBytes; uint32_t addr_len = sizeof(params.xClient); sys_time.timezone = 1; params.poll_interval = SNTP_POLL_INTERVAL; /* Attempt to open the socket. */ params.socket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); /* Set a time out so connect() will try connect over and over */ FreeRTOS_setsockopt( params.socket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); params.xClient.sin_port = FreeRTOS_htons(SNTP_PORT_NR); memset(&sntpmsg,0,sizeof(sntpmsg)); sntpmsg.li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT; for(;;) { while(ntp_addr==0) { ntp_addr=FreeRTOS_gethostbyname(SNTP_SERVER_ADDRESS_NAME); // try to connect 5 times after that returns 0 params.xClient.sin_addr = ntp_addr; } FreeRTOS_sendto(params.socket,&sntpmsg,sizeof(sntpmsg),0,¶ms.xClient,sizeof(params.xClient)); // send request usBytes=FreeRTOS_recvfrom(params.socket,&sntpresponse,sizeof(sntpresponse),0,¶ms.xClient,&addr_len); // wait for NTP's server response,blocking if(usBytes == SNTP_MSG_LEN) { /* Kiss-of-death packet. Use another server or increase SNTP_POLL_INTERVAL. */ if(sntpresponse.stratum == SNTP_STRATUM_KOD) { print_gen(s_KOD); params.poll_interval +=1000; } else if (((sntpresponse.li_vn_mode & SNTP_MODE_MASK) == SNTP_MODE_SERVER) || ((sntpresponse.li_vn_mode & SNTP_MODE_MASK) == SNTP_MODE_BROADCAST)) { getDate(FreeRTOS_ntohl(sntpresponse.receive_timestamp[0]),&sys_time); #if SNTP_PRINT_LOG PRINT_SYSTIME; #endif } } else //error { } vTaskDelay(params.poll_interval); } }