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

UNIXSocket does not work when socket type is DGRAM #3214

Closed
bew opened this issue Aug 30, 2016 · 3 comments · Fixed by #3750
Closed

UNIXSocket does not work when socket type is DGRAM #3214

bew opened this issue Aug 30, 2016 · 3 comments · Fixed by #3750

Comments

@bew
Copy link
Contributor

bew commented Aug 30, 2016

Hi !
I'm trying to make a wpa_supplicant front end in pure-crystal, and I need to connect to the server using Unix Socket with the DGRAM (datagram) socket type.

The UNIXSocket class provides a good abstraction, but there are some specificity when using DGRAM that are not handled :

client = UNIXSocket.new "/path/to/server", Socket::Type::DGRAM
client << "PING"
puts "Result = #{client.gets(4096)}"
client.close

This code will hang forever on client.gets(4096). It's not the server fault, I tested with wpa_supplicant server..
Found the answer on stackoverflow

The reason is that the socket is not properly configured when the DGRAM socket type is used :

With datagram sockets, specifically unix domain datagram sockets, the client has to bind() to its own endpoint, then connect() to the server's endpoint.

Another exemple is in wpa_cli source (a wpa_supplicant front end) at this line 93, where it creates the socket that will connect to the server :

  • socket : Create the socket
  • bind : Give the socket a name (<== this is the missing part)
  • connect : Connect to the server

I've made & push a dirty fix here

I don't really know if my fix is complete and how to implement this in crystal stdlib (naming/logic/..)
@asterite @ysbaddaden : You worked on this, maybe you can help ?

@bew bew changed the title UNIXSocket does not work when protocol is DGRAM UNIXSocket does not work when socket type is DGRAM Aug 30, 2016
@ysbaddaden
Copy link
Contributor

Good catch! UNIXSocket was only tested with STREAM, not DGRAM. I looked at Ruby and it doesn't provide any nicety, and instead relies on manual Socket instantiation (see this example).

Maybe UNIXSoket#initialize could take an optional local_path arg to bind the socket to, and document that this required for DGRAM? Maybe duplicating the UDPSocket#send and #receive methods would make sense? This will also require some specs to test the behavior.

@bew
Copy link
Contributor Author

bew commented Dec 10, 2016

I've made more research recently, on how to implement this, and ended up realizing that we can't unify all in UNIXSocket.

In the same way that :

  • TCPSocket is for STREAM socket
  • UDPSocket is for DGRAM socket

We will need to have something like StreamUNIXSocket & DGramUNIXSocket.

I currently don't know how to handle a socket pair from UNIXSocket#pair.

Do you agree ? Should I try and implement this ?

@ysbaddaden
Copy link
Contributor

I'd like to rework how sockets are currently implemented, to something a bit more Ruby-like.

I'd like a generic Socket class, with all the methods to bind, listen, accept, setsockopts, and so on. That would allow to create any kind of socket, like RAW sockets, have more control over sockets to build custom servers, for example DGRAM UNIX sockets, setting the SO_REUSEPORT option, binding client sockets to a local interface, and so on; without introducing too many special cases and many classes, methods or arguments.

Special classes, that is TCPSocket, TCPServer, UDPSocket, UNIXSocket and UNIXSocket would be convenient solutions to easily start servers or create client sockets (just like now).

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

Successfully merging a pull request may close this issue.

3 participants