What is the purpose of the `withFdSocket sock setCloseOnExecIfNeeded` call in Network.Socket example? - sockets

In the Network.Socket package, there is an echo server example. In the echo server, a call to withFdSocket sock setCloseOnExecIfNeeded is made just before actually binding to the socket. The relevant function is below:
open :: AddrInfo -> IO Socket
open addr = E.bracketOnError (openSocket addr) close $ \sock -> do
setSocketOption sock ReuseAddr 1
withFdSocket sock setCloseOnExecIfNeeded
bind sock $ addrAddress addr
listen sock 1024
return sock
The full example can be found on the Network.Socket package documentation.
What is the purpose of this call? It's my understanding that withFdSocket creates a file descriptor associated with the socket, and setCloseOnExecIfNeeded sets the CLOEXEC flag on the descriptor. However this descriptor is immediately 'discarded' and nothing is done with it.
Am I confused that the file descriptor always exists and withFdSocket just provides this existing descriptor, which we have to update with the flag in order for the socket to close when the program exits?

withFdSocket does not create an Fd; it just reads the one already stored inside the socket data structure.

Related

Why does sending ^D with netcat not trigger an EOF when reading from a Unix socket?

I am trying to write a server that will read from a Unix socket:
use std::io::prelude::*;
use std::os::unix::net::{UnixListener, UnixStream};
fn main() {
let socket_name = "socket";
let listener = match UnixListener::bind(&socket_name) {
Err(err) => panic!("Failed to bind to socket: {}.", err),
Ok(stream) => stream,
};
for mut stream in listener.incoming() {
match stream {
Ok(ref mut stream) => {
let msg = read(stream);
stream.write_all(msg.as_bytes()).expect("Echo");
}
Err(err) => panic!("Error occured when listening from the stream. {}", err),
}
}
fn read(stream: &mut UnixStream) -> String {
let mut s = String::new();
stream.read_to_string(&mut s).unwrap();
s
}
}
(playground)
On the client side I use nc: nc -U socket. I send some data and end it with ^D which should be an EOF. The docs for read_to_string say:
Read all bytes until EOF in this source, appending them to buf
Expected behavior:
After sending ^D on the client side the server responds with echo
Observed behavior:
Server doesn't recognize that EOF was sent and blocks. Only when the client breaks the connection the server prints the message and panics with the broken pipeline.
I send some data and end it with ^D which should be an EOF
It is, to the input of nc. That doesn't mean that the socket itself is closed:
When netcat is faced with an EOF on its standard input, it may or may
not close the sending part of its TCP connection, depending on which
version of netcat it is.
Solved: netcat (nc) doesn’t terminate at end of transmission
ctrl+d which sends an EOF on netcat's stdin: netcat noticed the EOF. It will send no further data through the socket. However, it
continues running and reading from the socket in case the server has
more data to send.
Unix : Epoll, catch ctrl+d and ctrl+c in server
For what it's worth, I cannot reproduce your problem on macOS 10.14.1 with the system-supplied nc.
You might be able to use the -q or -w options for your version of nc:
Assuming that after sending EOF connection will stay idle, you can use -w timeout option, which works for timeout being equal to zero
netcat doesn't terminate when stdin closes
You could also try being non-interactive:
$ echo 'hello' | nc -U socket
hello
See also:
read_to_end method never returns for UnixStream
Reading from a TcpStream with Read::read_to_string hangs until the connection is closed by the remote end
I had a similar issue. Try the nc -N flag.
This flag causes nc to send a shutdown(2) of the TCP socket when the input reaches EOF.
On an older version of Ubuntu (verified on 14.04), it behaved as though -N was always passed (and nc did not support -N).
On newer versions (verified on Ubuntu 20.04), it only exhibits this behavior when the -N flag is set.

Lua, how to read from unix file socket

i am realy struggling to connect and read from a existing unix file socket.
the socket exist, is Mode +rwx and should return a json oneliner (without newline).
(i have no Problem to read the socket on debian based systems like ncat -U /run/fastd.supernode.sock)
While i try to solve it on a embedded device TP-Link841v11-ND Mips (Fastd Socket on an OpenWRT / LEDE Router from TP Link) mainly only lua (and luasocket) is available.
i come so far
$ lua
> socket = require"socket"
> socket.unix = require"socket.unix"
> getme = socket.unix("/var/run/fastd.mesh_vpn.socket")
> print(getme:receive())
stdin:1: calling 'receive' on bad self (unix{client} expected, got userdata)
stack traceback:
[C]: in function 'receive'
stdin:1: in main chunk
[C]: ?
solution, for those who have similar problems
(as described here https://forum.freifunk.net/t/connect-fastd-socket-on-tp841v11-fastd-statistiken/13499 )
(you need to reconnect each time you wanna read socket)
$ lua
> require "socket"
> require "socket.unix"
> c = socket.unix()
> c:connect("/var/run/fastd.mesh_vpn.socket")
> print(c:receive())
You are missing several commands; see the complete example in this SO answer or this maillist discussion for further details.

sock = new UdpClient(ipAny) cause error > System.Net.Sockets.SocketException has been thrown. Access denied

My Environment
MacOS X 10.8.5
Unity 5.1.1f
I am trying to use code to access NTP server.
http://ftvoid.com/blog/post/847
When I try the code, I have an error at new UdpClient(ipAny)
private void Request() {
// Open socket
ipAny = new IPEndPoint(IPAddress.Any, 123);
sock = new UdpClient(ipAny);
The error message is
System.Net.Sockets.SocketException has been thrown
Access denied
Instead of the following
sock = new UdpClient(ipAny);
if I use the following, it works.
sock = new UdpClient();
My Questions are
What's the cause of the error?
Is it O.K. to use sock = new UpdClient()?
Should be fine. The constructor you are using is for local port binding. Not sure why you need that. From the docs:
You do not need to specify a local IP address and port number for sending and receiving data. If you do not, the underlying service provider will assign the most appropriate local IP address and port number.
https://msdn.microsoft.com/en-us/library/k227d11f(v=vs.110).aspx
I'd use the new UpdClient() as you suggested.

how to know if a server is listening at a port

I have created a TCP socket at one end of my application. Say the end is 1. This socket closes after about 10sec. Now the other side of my application (end 2) is allowed to connect to the above created socket. Im coding this socket app in python, so suppose my end 2 is trying to connect to the TCP socket, but the socket no longer exists, my program terminates because of some exception. I dont want that to happen. It's like there is a while loop in my end 2. So if a connection is not available it goes back and wait.
Are you handling the exception correctly ..
try:
s.connect((host,port))
except socket.error, (value,message):
if s:
s.close()
print "Could not open socket: " + message
"""Code to handle a retry"""
On getting an error .. you can retry by doing a bind and listen again.. Also you need to have retry count ..say 5 and then perhaps exit.

Lua Socket cannot be properly stopped by Ctrl+C

I have a standalone lua script that uses lua sockets to connect to a server via TCP IP. It uses receive call to receive data from that server. It works, however, when I try to stop it with Ctrl+C, one of the two scenarios is happening:
-If there is currently no traffic and receive is waiting, Ctrl+C will have no effect. The program will continue to run, and will have to be terminated by kill.
-If there is traffic, the program will exit with the below printout and with the socket still open and with the server not accepting another connection:
lua: luaSocketTest.lua:15: interrupted!
stack traceback:
[C]: in function 'receive'
luaSocketTest.lua:15: in function 'doWork'
luaSocketTest.lua:22: in main chunk
[C]: ?
I tried using pcall to solve the second scenario, without success. pcall doesn't return, the process still throws the error.
Sample of my program is below:
local socket = require ("socket")
local ip = "localhost"
local port = 5003
function doWork ()
print ("Starting socket: "..ip..":"..port)
client = assert(socket.connect(ip, port))
print ("Socket Accepted")
client:send("TEST TEST")
while 1 do
local byte, err = client:receive (1)
if not err then
print (byte)
end
end
end
while 1 do
local status = pcall(doWork())
print ("EXITED PCALL WITH STATUS: "..tostring(status))
if not status then client:close() end
end
This would be quite a change, but you could employ lua-ev. It allows to add Signal handlers, which is exactly what is required to react to ctrl-c.
local socket = require'socket'
-- make connect and send in blocking mode
local client = socket.connect(ip,port)
client:send('TEST TEST')
-- make client non-blocking
client:settimeout(0)
ev.IO.new(function()
repeat
local data,err,part = client:receive(10000)
print('received',data or part)
until err
end,client:getfd(),ev.READ):start(ev.Loop.default)
local ev = require'ev'
local SIGINT = 2
ev.Signal.new(function()
print('SIGINT received')
end,SIGINT):start(ev.Loop.default)
ev.Loop.default:loop()