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

Add non-blocking alternative to EthernetClient::connect() #222

Open
mghie opened this issue May 1, 2023 · 0 comments
Open

Add non-blocking alternative to EthernetClient::connect() #222

mghie opened this issue May 1, 2023 · 0 comments

Comments

@mghie
Copy link
Contributor

mghie commented May 1, 2023

I have a program which needs to always update outputs in a timely manner, even when calling EthernetClient::connect() (which can block for the number of milliseconds set with setConnectionTimeout()).

I have modified the current code:

int EthernetClient::connect(IPAddress ip, uint16_t port)
{
	if (_sockindex < MAX_SOCK_NUM) {
		if (Ethernet.socketStatus(_sockindex) != SnSR::CLOSED) {
			Ethernet.socketDisconnect(_sockindex); // TODO: should we call stop()?
		}
		_sockindex = MAX_SOCK_NUM;
	}
#if defined(ESP8266) || defined(ESP32)
	if (ip == IPAddress((uint32_t)0) || ip == IPAddress(0xFFFFFFFFul)) return 0;
#else
	if (ip == IPAddress(0ul) || ip == IPAddress(0xFFFFFFFFul)) return 0;
#endif
	_sockindex = Ethernet.socketBegin(SnMR::TCP, 0);
	if (_sockindex >= MAX_SOCK_NUM) return 0;
	Ethernet.socketConnect(_sockindex, rawIPAddress(ip), port);
	uint32_t start = millis();
	while (1) {
		uint8_t stat = Ethernet.socketStatus(_sockindex);
		if (stat == SnSR::ESTABLISHED) return 1;
		if (stat == SnSR::CLOSE_WAIT) return 1;
		if (stat == SnSR::CLOSED) return 0;
		if (millis() - start > _timeout) break;
		delay(1);
	}
	Ethernet.socketClose(_sockindex);
	_sockindex = MAX_SOCK_NUM;
	return 0;
}

to the following:

int EthernetClient::connect(IPAddress ip, uint16_t port)
{
	int ret = beginConnect(ip, port);
	if (ret >= 0) return ret;

	uint32_t start = millis();
	while (1) {
		ret = endConnect();
		if (ret >= 0) return ret;
		if (millis() - start > _timeout) break;
		delay(1);
	}
	Ethernet.socketClose(_sockindex);
	_sockindex = MAX_SOCK_NUM;
	return 0;
}

int EthernetClient::beginConnect(IPAddress ip, uint16_t port)
{
	if (_sockindex < MAX_SOCK_NUM) {
		if (Ethernet.socketStatus(_sockindex) != SnSR::CLOSED) {
			Ethernet.socketDisconnect(_sockindex); // TODO: should we call stop()?
		}
		_sockindex = MAX_SOCK_NUM;
	}
	if (ip == IPAddress(0ul) || ip == IPAddress(0xFFFFFFFFul)) return 0;
	_sockindex = Ethernet.socketBegin(SnMR::TCP, 0);
	if (_sockindex >= MAX_SOCK_NUM) return 0;
	Ethernet.socketConnect(_sockindex, rawIPAddress(ip), port);
	return -1;
}

int EthernetClient::endConnect()
{
	uint8_t stat = Ethernet.socketStatus(_sockindex);
	if (stat == SnSR::ESTABLISHED) return 1;
	if (stat == SnSR::CLOSE_WAIT) return 1;
	if (stat == SnSR::CLOSED) return 0;
	return -1;
}

Now instead of calling connect() I can call beginConnect() and then repeatedly call endConnect() during the main loop until it returns either 1 on success or 0 on failure.

If there is interest to include this into the library I can update the documentation (which is not up-to-date for connect() anyway) and create a PR. Please let me know.

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

1 participant