FreeRTOSIP-TCP Connection issue

joehinkle wrote on Tuesday, August 09, 2016:

I’ve been using UDP for some time now.

Attempting to use TCP with this stack.

In another post, I had an issue with FreeRTOS_select not working with a Listen socker because a FreeRTOSConfig setting was in conflict with the FreeRTOS_select’s capability.

I’m wondering if the issue that follows is also associated with conflicting CONFIG settings.

My TCP usage is a small web server. Chrome is attempting to connect.

FreeRTOSIP identifies the incoming connection and my code issues FreeRTOS_accept.

Chrome does not like the connections and closes all of the connections without ever attempting to send data to the connection.

I have a WireShark listing showing MY side of the communication – notice all of the re-tries.

Following the WireShark listing are the stack’s debug messages that are generated during the process.

Chrome is 192.1689.1.37
FreeRTOSIP is 192.168.1.12

Stack Debug Listing:

Debugger Active IP 192.168.1.37
PixelBoard Debugger Active IP 192.168.1.12
D:7:28 AM:9901642 -> Gain: Socket 80 now has 1 / 3 child

D:7:28 AM:9901643 -> prvSocketSetMSS: 1460 bytes for c0a80125ip:51148

D:7:28 AM:9901643 -> Socket 80 -> c0a80125ip:51148 State eCLOSED->eSYN_FIRST

D:7:28 AM:9901644 -> Socket 80 -> c0a80125ip:51148 State eSYN_FIRST->eSYN_RECEIVED

D:7:28 AM:9901644 -> Gain: Socket 80 now has 2 / 3 children

D:7:28 AM:9901644 -> prvSocketSetMSS: 1460 bytes for c0a80125ip:51149

D:7:28 AM:9901644 -> Socket 80 -> c0a80125ip:51149 State eCLOSED->eSYN_FIRST

D:7:28 AM:9901644 -> Socket 80 -> c0a80125ip:51149 State eSYN_FIRST->eSYN_RECEIVED

D:7:28 AM:9901892 -> Gain: Socket 80 now has 3 / 3 children

D:7:28 AM:9901892 -> prvSocketSetMSS: 1460 bytes for c0a80125ip:51150

D:7:28 AM:9901893 -> Socket 80 -> c0a80125ip:51150 State eCLOSED->eSYN_FIRST

D:7:28 AM:9901893 -> Socket 80 -> c0a80125ip:51150 State eSYN_FIRST->eSYN_RECEIVED

D:7:28 AM:9901930 -> xTCPCheckNewClient[0]: client on port 80

D:7:28 AM:9901931 -> Connection Using 1

D:7:28 AM:9901931 -> xTCPCheckNewClient[0]: client on port 80

D:7:28 AM:9901931 -> Connection Using 2

D:7:28 AM:9901931 -> Connection Using 3

D:7:28 AM:9904642 -> eSYN_RECEIVED: ACK expected, not SYN: peer missed our SYN+ACK

D:7:28 AM:9904642 -> Socket 80 -> c0a80125ip:51148 State eSYN_RECEIVED->eSYN_FIRST

D:7:28 AM:9904643 -> Socket 80 -> c0a80125ip:51148 State eSYN_FIRST->eSYN_RECEIVED

D:7:28 AM:9904643 -> eSYN_RECEIVED: ACK expected, not SYN: peer missed our SYN+ACK

D:7:28 AM:9904643 -> Socket 80 -> c0a80125ip:51149 State eSYN_RECEIVED->eSYN_FIRST

D:7:28 AM:9904643 -> Socket 80 -> c0a80125ip:51149 State eSYN_FIRST->eSYN_RECEIVED

D:7:28 AM:9904892 -> eSYN_RECEIVED: ACK expected, not SYN: peer missed our SYN+ACK

D:7:28 AM:9904892 -> Socket 80 -> c0a80125ip:51150 State eSYN_RECEIVED->eSYN_FIRST

D:7:28 AM:9904892 -> Socket 80 -> c0a80125ip:51150 State eSYN_FIRST->eSYN_RECEIVED

D:7:28 AM:9910642 -> eSYN_RECEIVED: ACK expected, not SYN: peer missed our SYN+ACK

D:7:28 AM:9910642 -> Socket 80 -> c0a80125ip:51148 State eSYN_RECEIVED->eSYN_FIRST

D:7:28 AM:9910643 -> Socket 80 -> c0a80125ip:51148 State eSYN_FIRST->eSYN_RECEIVED

D:7:28 AM:9910643 -> eSYN_RECEIVED: ACK expected, not SYN: peer missed our SYN+ACK

D:7:28 AM:9910643 -> Socket 80 -> c0a80125ip:51149 State eSYN_RECEIVED->eSYN_FIRST

D:7:28 AM:9910643 -> Socket 80 -> c0a80125ip:51149 State eSYN_FIRST->eSYN_RECEIVED

D:7:28 AM:9910892 -> eSYN_RECEIVED: ACK expected, not SYN: peer missed our SYN+ACK

D:7:28 AM:9910893 -> Socket 80 -> c0a80125ip:51150 State eSYN_RECEIVED->eSYN_FIRST

D:7:28 AM:9910895 -> Socket 80 -> c0a80125ip:51150 State eSYN_FIRST->eSYN_RECEIVED

D:7:28 AM:9912929 -> Killing stuck session 0

D:7:28 AM:9912930 -> Lost: Socket 80 now has 2 / 3 children

D:7:28 AM:9912930 -> FreeRTOS_closesocket[80 to c0a80125ip:51148]: buffers 44 socks 3

D:7:28 AM:9912931 -> Closed Socket 1

D:7:28 AM:9912931 -> Killing stuck session 1

D:7:28 AM:9912931 -> Lost: Socket 80 now has 1 / 3 child

D:7:28 AM:9912932 -> FreeRTOS_closesocket[80 to c0a80125ip:51149]: buffers 44 socks 2

D:7:28 AM:9912932 -> Closed Socket 2

D:7:28 AM:9912932 -> Killing stuck session 2

D:7:28 AM:9912932 -> Lost: Socket 80 now has 0 / 3 children

D:7:28 AM:9912933 -> FreeRTOS_closesocket[80 to c0a80125ip:51150]: buffers 44 socks 1

D:7:28 AM:9912933 -> Closed Socket 3


Have you seen this issue before?

Are there any config settings that may be causing the issue.

Thanks in advance for any comments.

Joe

heinbali01 wrote on Tuesday, August 09, 2016:

You’re too quick.

I’m just ready testing your earlier source code and now you’re posting +TCP logging.

Please find attached a simple TCP server that uses Select(). I tested it on real hardware.

What hardware platform are you using now, still a NXP K64?

About the logging: did you also have a PCAP file from Wireshark, not only a print-screen?

Chrome does not like the connections

It seems to me that Chrome doesn’t receive any response at all, for some reason there is a one-way traffic. Strange though that Wireshark doesn see +TCP responses (SYN+ACK)

/* Standard includes. */
#include <stdint.h>
#include <stdio.h>

/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"

#if( USE_WIFI_SERVER != 0 )

static unsigned short ListenPort = 8008;

static Socket_t xListenSocket;

#define	PRIORITY_HTTP_TASK						3
#define STACK_SIZE_HTTP_TASK		340

extern void clearWDT (void); /* Should be called by each process */


#define MAX_SESSIONS		4
#define WS_HEADER			1

typedef struct xSesssion 
{
	Socket_t S;
} Sesssion_t;

 #define WF_DataWasSentLookForComplete		1

static TaskHandle_t pxHTTPTask;

static char pcBuffer[ 256 + 1 ];

static Sesssion_t xSessions[ MAX_SESSIONS ];
static SocketSet_t  xSocketSet;

void AcceptConnection()
{
struct freertos_sockaddr xAddress;
socklen_t xAddressLength = ( socklen_t ) sizeof( xAddress );
BaseType_t xSessionNr;

	Socket_t xSocket = FreeRTOS_accept( xListenSocket, &xAddress, &xAddressLength  );

	FreeRTOS_printf( ( "FreeRTOS_accept returns %p\n", xSocket ) );
	if( xSocket != NULL )
	{
	UBaseType_t xReceiveTimeOut = 0ul;

		/* The call to FreeRTOS_recv() will be non-blocking. */
		FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );       
		for( xSessionNr = 0; xSessionNr < MAX_SESSIONS; xSessionNr++ )
		{
			if( xSessions[xSessionNr].S == FREERTOS_INVALID_SOCKET )
			{
				memset( xSessions + xSessionNr, 0, sizeof xSessions[ xSessionNr ] );
				xSessions[xSessionNr].S = xSocket;
				FreeRTOS_FD_SET( xSocket, xSocketSet, eSELECT_READ | eSELECT_EXCEPT );
				break;
			}
		}
	}
}

void http_server( void *pvParameters )
{
UBaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000ul );
BaseType_t xResult, xSessionNr;
struct freertos_sockaddr server_addr;
UBaseType_t TimeoutActive = pdFALSE;

	/* loop through list of open sessions looking for work */
	for(xSessionNr = 0; xSessionNr < MAX_SESSIONS; xSessionNr++)
	{
		xSessions[xSessionNr].S = FREERTOS_INVALID_SOCKET;
	}

    while(1)
    {

            /* Create a TCP socket. */
        xListenSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
        if( xListenSocket != FREERTOS_INVALID_SOCKET )
		{
            break;
		}
TryAgain:   
        vTaskDelay( pdMS_TO_TICKS( 100 ) );
    }

 /* Set a time out so accept() will just wait for a connection. */
    FreeRTOS_setsockopt( xListenSocket,
                         0,
                         FREERTOS_SO_RCVTIMEO,
                         &xReceiveTimeOut,
                         sizeof( xReceiveTimeOut ) );       

    memset(&server_addr, '\0', sizeof(server_addr));      
    server_addr.sin_port = FreeRTOS_htons( ListenPort );
    server_addr.sin_addr = FreeRTOS_GetIPAddress(); // Single NIC, currently not used

    // Bind the address to the socket. 
    if( FreeRTOS_bind( xListenSocket, &server_addr, sizeof( server_addr ) ) == -1 )
    {
        FreeRTOS_closesocket( xListenSocket );
        xListenSocket = FREERTOS_INVALID_SOCKET;
        goto TryAgain;
    }

    FreeRTOS_printf( ("Socket created and Bind.\n" ) );

    while(1)
    {
        xSocketSet = FreeRTOS_CreateSocketSet();
        if( xSocketSet )
		{
            break;
		}

        vTaskDelay( pdMS_TO_TICKS( 100 ) );
    }

    //Listen to incoming connections
    xResult = FreeRTOS_listen( xListenSocket , MAX_SESSIONS );

    // add listen to socket set 
    FreeRTOS_FD_SET( xListenSocket, xSocketSet, eSELECT_READ );

    //Accept and incoming connection
    FreeRTOS_printf( ("Waiting for incoming connections... (xResult = %ld)\n", xResult ) );

    while(1)
    {
		clearWDT ();

        /* See if any of the sockets have input or ready to send */
		/* Wait at most 10 seconds. */
        xResult = FreeRTOS_select( xSocketSet, ( pdMS_TO_TICKS( 10000 ) ) );    // Blocks until activity

        if(xResult < 0)
		{
		static BaseType_t xLastError;

			if( xLastError != xResult )
			{
				xLastError = xResult;
				FreeRTOS_printf( ("Select returns %ld\n", xResult ) );
			}
		}
        else if( xResult > 0 )
        {
			FreeRTOS_printf( ("Select returns %ld\n", xResult ) );
            // check if new read on listen
            if( ( FreeRTOS_FD_ISSET( xListenSocket, xSocketSet ) & eSELECT_READ ) != 0 )  // read on listen means new connection waiting
			{
                AcceptConnection();
			}
        }

		/* Work on the socket list. */
		for( xSessionNr = 0; xSessionNr < MAX_SESSIONS; xSessionNr++ )
		{
		Socket_t xSocket = xSessions[ xSessionNr ].S;

			if( xSocket != FREERTOS_INVALID_SOCKET )
			{
			BaseType_t xLength;

				xLength = FreeRTOS_recv( xSocket, pcBuffer, sizeof( pcBuffer ) - 1, 0L );

				if( xLength < 0 )
				{
					if( xLength != -pdFREERTOS_ERRNO_EAGAIN )
					{
						FreeRTOS_printf( ("Connection lost, socket will be closed.\n" ) );
						FreeRTOS_FD_CLR( xSocket, xSocketSet, eSELECT_ALL );
						FreeRTOS_closesocket( xSocket );
						/* Mark as free. */
						xSessions[ xSessionNr ].S = FREERTOS_INVALID_SOCKET;
					}
				}
				else if( xLength > 0 )
				{
					FreeRTOS_send( xSocket, pcBuffer, xLength, 0 );
				}
				break;
			}
		}
	}
}

void http_server_install()
{
	if( pxHTTPTask == NULL )
	{
		/* Call this function once to start the test with FreeRTOS_accept(). */
		xTaskCreate( http_server, "http_server", STACK_SIZE_HTTP_TASK, NULL, PRIORITY_HTTP_TASK, &pxHTTPTask );
	}

}

#endif /* USE_WIFI_SERVER != 0 */

joehinkle wrote on Tuesday, August 09, 2016:

Yes I have a pcap file.

joehinkle wrote on Tuesday, August 09, 2016:

I resolved the other issue We spoke about – see that post.

In your example server above – what does function clearWDT (); do?

It is missing from the code?

Joe

joehinkle wrote on Tuesday, August 09, 2016:

I’ve implemented you server above.

Same connection issue.

I have include pcap files for execution on Chrome and IE.

Any IP config setting that could be related?

I wrote the EMAC - driver. Any potential issue I caused there? The driver was running in another port – no issue.

Here is a debug dump from YOUR web server. If you look at the pcap file, I still see a lot of re-transmissions.

Do you see any behavior difference in my server and yours?

The two Test_WS files are YOUR web server.

Web Browser is 192.168.1.37
FreeRTOSIP is 192.168.1.12



Thanks.

Joe

Debug dump YOUR Server

D:9:47 AM:18280267 -> Gain: Socket 8008 now has 1 / 4 child

D:9:47 AM:18280267 -> prvSocketSetMSS: 1460 bytes for c0a80125ip:52610

D:9:47 AM:18280268 -> Socket 8008 -> c0a80125ip:52610 State eCLOSED->eSYN_FIRST

D:9:47 AM:18280268 -> Socket 8008 -> c0a80125ip:52610 State eSYN_FIRST->eSYN_RECEIVED

D:9:47 AM:18283269 -> eSYN_RECEIVED: ACK expected, not SYN: peer missed our SYN+ACK

D:9:47 AM:18283270 -> Socket 8008 -> c0a80125ip:52610 State eSYN_RECEIVED->eSYN_FIRST

D:9:47 AM:18283270 -> Socket 8008 -> c0a80125ip:52610 State eSYN_FIRST->eSYN_RECEIVED

S:9:48 AM:18285955 -> Select returns 1

S:9:48 AM:18285955 -> FreeRTOS_accept returns 2000fda8

D:9:48 AM:18289264 -> eSYN_RECEIVED: ACK expected, not SYN: peer missed our SYN+ACK

D:9:48 AM:18289264 -> Socket 8008 -> c0a80125ip:52610 State eSYN_RECEIVED->eSYN_FIRST

D:9:48 AM:18289264 -> Socket 8008 -> c0a80125ip:52610 State eSYN_FIRST->eSYN_RECEIVED

D:9:48 AM:18301266 -> Gain: Socket 8008 now has 2 / 4 children

D:9:48 AM:18301267 -> prvSocketSetMSS: 1460 bytes for c0a80125ip:52612

D:9:48 AM:18301267 -> Socket 8008 -> c0a80125ip:52612 State eCLOSED->eSYN_FIRST

D:9:48 AM:18301267 -> Socket 8008 -> c0a80125ip:52612 State eSYN_FIRST->eSYN_RECEIVED

D:9:48 AM:18304266 -> eSYN_RECEIVED: ACK expected, not SYN: peer missed our SYN+ACK

D:9:48 AM:18304266 -> Socket 8008 -> c0a80125ip:52612 State eSYN_RECEIVED->eSYN_FIRST

D:9:48 AM:18304266 -> Socket 8008 -> c0a80125ip:52612 State eSYN_FIRST->eSYN_RECEIVED

S:9:48 AM:18305955 -> Select returns 1

S:9:48 AM:18305955 -> FreeRTOS_accept returns 20010f68

D:9:48 AM:18310266 -> eSYN_RECEIVED: ACK expected, not SYN: peer missed our SYN+ACK

D:9:48 AM:18310267 -> Socket 8008 -> c0a80125ip:52612 State eSYN_RECEIVED->eSYN_FIRST

D:9:48 AM:18310267 -> Socket 8008 -> c0a80125ip:52612 State eSYN_FIRST->eSYN_RECEIVED


joehinkle wrote on Tuesday, August 09, 2016:

Missed your question.

Yes – still same NXP Kinetis K64 (Use to be FreeScale)

Joe

joehinkle wrote on Tuesday, August 09, 2016:

Hein:

It just occurred to me, you might think this is about the Listening / Select issue I post about over the weekend.

It’s NOT. I resolved that issue – I believe you folks have a CONFIG option issue that needs looking into.

This is a Connection issue AFTER the listening has accepted the connection.

Joe

heinbali01 wrote on Tuesday, August 09, 2016:

Hi Joe,

clearWDT ()

Sorry I left that in, it’s my Watch Dog Timer, every task must call it regularly.

Your last logging shows the same: the client doesn’t seem to receive any TCP packets.

Yes I have a pcap file.

I still don’t the PCAP file attached?

Normally when users are developing a EMAC / +TCP driver, they get in touch with us directly. This shortens the development time and it decreases frustrations. I already invited you to contact us :slight_smile: You can reach me as h point tibosch at freertos point org.

There is already a port for K63F, but I’m not sure if that would help you?

I’ve just posted a working example of the use of FreeRTOS_select() in this thread. I tested it with :

#define ipconfigTCP_HANG_PROTECTION        1

Have you tried it already?

There is no known issue (yet) with the hang protection. It is normally used along with ipconfigTCP_KEEP_ALIVE, which causes ALIVE messages to be exchanged.

Have you already tried the example HTTP server?

    FreeRTOS-Plus-TCP\protocols\HTTP\FreeRTOS_HTTP_server.c

it also uses FreeRTOS_select() and I it is often used along with ipconfigTCP_HANG_PROTECTION.

Regards, Hein

heinbali01 wrote on Tuesday, August 09, 2016:

Our posts keep on crossing each other…

I’ll attach a PCAP of the communication that I just saw. It is sending three times “Hello world” to the server and disconnect.

The logging shows this:

    70.379 [10]: Select returns 1
    70.380 [10]: FreeRTOS_accept returns d0233ec8
    71.854 [10]: Select returns 1
    72.894 [10]: Select returns 1
    73.917 [10]: Select returns 1
    75.015 [10]: Select returns 4
    75.015 [10]: Connection lost, socket will be closed.

Regards.

joehinkle wrote on Wednesday, August 10, 2016:

Update:

Issue is resolved.

Stack GREAT!!.
User had issue.

I was too knowledable about stack and driver design that I read more into the porting requirements than what +TCP wanted.

I am using buffer_allocation_1 which uses statically defined network buffers.

When I designed the driver’s transmit function I assumed the return indicated if the networkbuffer was actually transmitted.

If I did not have an empty xmit buffer slot, I returned FALSE back to the stack and DID NOT release the buffer. The stack thought the buffer was released and reused it, which happened to be a TCP reply to a client with the wrong port number. My client did NOT receive a proper connection SYN+ACK to the required port … so it bailed.

Hein was extreemly helpful in resolving the issue which was with my transmit driver. I now spin until the message can be transmitted and always release EVERY buffer … transmitted or not.

Great help from Hein at FreeRTOS.

Joe