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

what(): connect: No buffer space available #3986

Closed
thamerla opened this issue Apr 20, 2019 · 10 comments
Closed

what(): connect: No buffer space available #3986

thamerla opened this issue Apr 20, 2019 · 10 comments

Comments

@thamerla
Copy link

I made boost::asio program that connects using TCP. On pure Linux it works fine, on WSL it throws the error in tittle.

Any idea how to fix it? Editing parameters doesn't work on WSL apparently.

@thamerla
Copy link
Author

@Biswa96 @therealkenc can I send it using email? Private code.

@thamerla
Copy link
Author

@Biswa96 I thought that it happened due to the size of data I was sending but it seems even connection creation throws it. I will send a sample soon.

@thamerla
Copy link
Author

Alright here's a sample.

What I am trying to achieve: TCP punchthrough (basically 2 clients connecting at the same time).
However, localhost should do the job. Requires boost::asio and linking against boost_system (-lboost_system).

#include <iostream>
#include <boost/asio.hpp>
#include <thread>

using boost::asio::ip::tcp;
using namespace std;

typedef unsigned short int us;

struct Client {
	string ip;
	us port;
};

void usage()
{
	cout << "<string> friendIp <unsigned short int> friendPort <unsigned short int> localPort" << endl;
}

string readMessage(tcp::socket& socket)
{
	char buffer[200];
	socket.read_some(boost::asio::buffer(buffer, 200));

	string data(buffer);
	return data;
}

void sendMessage(tcp::socket& socket, string message)
{
	boost::asio::write(socket, boost::asio::buffer(&message, sizeof(message)));
}

tcp::socket connect(Client client, us local_port)
{
    boost::asio::io_service io_service;

    tcp::socket socket(io_service, boost::asio::ip::tcp::v4());

    boost::asio::socket_base::reuse_address option(true);
    socket.set_option(option);

        socket.bind(boost::asio::ip::tcp::endpoint(
      boost::asio::ip::tcp::v4(), local_port));

    boost::system::error_code err;
	cout << "Trying to connect..." << endl;
	int i = 1;
    do {
    socket.connect(tcp::endpoint(boost::asio::ip::address::from_string(client.ip.c_str()), client.port), err);
	cout << "Connection try nr " << i << endl;
	
	if(err.value() > 0)
		cout << "Error code: " << err.value() << endl;
	
	++i;
    } while(err.value());
    return socket;
}

void serve(us port)
{
    boost::asio::io_service io_service;
    tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), port ));
    tcp::socket socket(io_service);

    acceptor.accept(socket);
}

int main(int argc, char* argv[])
{
    if(argc < 4) 
	{
		usage();
		return 0;
	}

	string fr_ip = argv[1];
	unsigned short int fr_port = atoi(argv[2]);
	unsigned short int local_port = atoi(argv[3]);

	
	std::thread server_thread(serve, local_port);
	
	Client fr;
	fr.ip = fr_ip;
	fr.port = fr_port;

	auto s = connect(fr, local_port);
	string m = "hi from small laptop";
	sendMessage(s, m);
	m = readMessage(s);
	cout << "Message from fr: " << m << endl;
	server_thread.join();

  return 0;
}

@therealkenc
Copy link
Collaborator

therealkenc commented Apr 21, 2019

./a.out 127.0.0.1 7000 7001 yields the same output on WSL as Real Linux -- stream of ECONNREFUSED. No CLI no usage no strace, which is most unfortunate.

boost::asio::socket_base::reuse_address option(true);
socket.set_option(option);

Gonna say #3909 for lack.

[edit] With ./a.out 127.0.0.1 7000 7000 below. Also same output as Real Linux (including the junk). Unlikely the WSL version matters but never know.

image

@thamerla
Copy link
Author

@therealkenc
./a.out 127.0.0.1 7000 7001 yields the same output on WSL as Real Linux -- stream of ECONNREFUSED. No CLI no usage no strace, which is most unfortunate.

Sure, because as I said - 2 clients connecting at the sime time. So you should run a second console with 2nd client. For me it works on localhost. Problem with buffer starts when connecting outside.

@thamerla
Copy link
Author

@therealkenc I can't really reproduce it anymore after using some googled command to increase buffer space on WSL Linux.

@therealkenc
Copy link
Collaborator

googled command to increase buffer space on WSL Linux.

What command.

There aren't any network tunables on WSL (WSL doesn't have a network stack). The /proc entries aren't emulated presently. Windows command, maybe, plausibly. Can't say for lack of ENOBUFS (really WSAENOBUFS under the hood) repro to follow here.

In any event, thanks for the report. Closing for lack of actionable, but the issue can serve as a reasonable search target if it comes up again.

@thamerla
Copy link
Author

@therealkenc My guess is that it is a Windows limit that I hit. To setup TCP punchthrough for NAT I need to start connecting A ---- > B B ------> A at the same time. So I get a bunch of requests that are refused before real connection is created. And this seems to hit a hardcoded limit. I guess rebooting my machine did the job.

You can consult with networking team at Microsoft if this is right explanation of getting this error.

Besides another "weirdness" on Windows - ports are automatically reused across sockets, no extra config required while on Linux it throws port already in use.

So I guess there's another problem WSL team needs to face someday - differences between behavior on Linux and on Windows re: networking.

@therealkenc
Copy link
Collaborator

So I get a bunch of requests that are refused before real connection is created.

That'll definitely trigger #3951 (formerly #2913). However your OP issue title implies a ENOBUFS contrast EINVAL.

I guess rebooting my machine did the job.

Yes. That or restarting LxssManager.

And this seems to hit a hardcoded limit.

No, all the ip4v limits are configurable on Windows too, as opposed to hard-coded. With effort. But the defaults allow teenagers to download Game of Thrones using (Windows) bittorrent without too much trouble, so that's probably not the cause of your ENOBUFS (in isolation).

Besides another "weirdness" on Windows - ports are automatically reused across sockets, no extra config required while on Linux it throws port already in use.

That's #3909.

@thamerla
Copy link
Author

@therealkenc happened again for no reason, I will try to make a repro.

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

No branches or pull requests

2 participants