Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential NAT issue #81

Open
juanwinsor opened this issue Jan 22, 2025 · 2 comments
Open

Potential NAT issue #81

juanwinsor opened this issue Jan 22, 2025 · 2 comments

Comments

@juanwinsor
Copy link

We are running a PLC simulator in a VM on a hardcoded IP address. We use NAT to bridge the host pc (which is running our modbus application), and the vm.

When I connect I receive a handful of timeouts and then it starts spitting out NMBS_ERROR_INVALID_TCP_MBAP error non stop. The logic triggering the error is the transaction id in the recv_res_header function

if (nmbs->platform.transport == NMBS_TRANSPORT_TCP) {
    if (nmbs->msg.transaction_id != req_transaction_id)
        return NMBS_ERROR_INVALID_TCP_MBAP;
}

Any help appreciated, thanks

@debevv
Copy link
Owner

debevv commented Jan 23, 2025

Hi, I don't think the NAT can cause any kind of alteration in the network packets.
At first glance looks like maybe you are connecting to the wrong address or port and whatever server is on the other side is responding with something that the library is randomly interpreting as a message with invalid MBAP.
Try do add a print or to debug that piece of code to understand what it is receiving as response.

@juanwinsor
Copy link
Author

Hi, thanks for your reply.

I've verified its connecting to the correct server.

when i get a connected callback from my tcp socket, that is when i initiate polling (we have a setup on the actual subnet without nat, that is working). There does seem to be some sort of connection delay to the PLC simulator when we're connecting through nat, I start polling right away but get timeouts for my first few requests before the MBAP errors.

Perhaps I'm not handling the timeouts correctly and that's offsetting the rest of the data? would you mind having a look at my read function to see if i've misinterpreted the instructions?

this is c++ in unreal

int32_t read_fd(uint8_t* buf, uint16_t count, int32_t timeout_ms, void* arg)
{
	if (!arg) {
		return -1;
	}	

	FSocket* tcpSocket = (FSocket*)arg;

	TArray<uint8> data;
	int32 total = 0;

	// register beginning of frame
	FDateTime timeStartRead = FDateTime::UtcNow();

	while (total != count)
	{
		// if we can read something		
		uint32 PendingDataSize = 0;


		// if timeout == 0 we should read once non-blocking and return immediately.
		if (timeout_ms == 0)
		{
			int32 BytesRead = 0;

			if (tcpSocket->HasPendingData(PendingDataSize))
			{
				tcpSocket->Recv(buf, PendingDataSize, BytesRead);
			}

			return BytesRead;
		}


		// keep going until we have no data.
		if (tcpSocket->HasPendingData(PendingDataSize))
		{
			// allocate space for the buffer
			int32 BytesRead = 0;

			// read as much data from the buffer as we can up to the size of (count - total)
			if (tcpSocket->Recv(buf + total, FMath::Min<int32>(PendingDataSize, count - total), BytesRead, ESocketReceiveFlags::WaitAll))
			{
				// increment total bytes
				total += BytesRead;

				if (BytesRead < 0)
				{
					// transport error
					return -1;
				}
			}
			else
			{
				// error reading socket, throw transport error
				return -1;
			}
		}

		// if there is a timeout specified, we check the current time against the time recorded at the start of the loop to see if we should force a timeout
		if (timeout_ms >= 0)
		{
			// timeout check
			FDateTime timeEndOfTick = FDateTime::UtcNow();
			FTimespan tickDuration = timeEndOfTick - timeStartRead;
			if (tickDuration.GetTotalMilliseconds() >= timeout_ms)
			{
				// return 0 to (count - 1) results in a timeout
				return 0;
			}
		}
		
	}

	return total;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants