nickva commented on PR #4729:
URL: https://github.com/apache/couchdb/pull/4729#issuecomment-1689241307
A bit more of a cleaned up connection script version which should work on
macos, linux and freebsd:
```erlang
#!/usr/bin/env escript
is_closed(Sock) ->
OsType = os:type(),
case tcp_info_opt(OsType) of
{raw, _, _, _} = TcpInfoOpt ->
case inet:getopts(Sock, [TcpInfoOpt]) of
{ok, [{raw, _, _, <<State:8/native, _/binary>>}]} ->
tcp_fsm_state(State, OsType);
{ok, []} ->
false;
{error, einval} ->
% Already cleaned up
true;
{error, _} ->
false
end;
undefined ->
false
end.
% All OS-es have the tcpi_state (uint8) as first member of tcp_info struct
tcp_info_opt({unix, linux}) ->
%% include/netinet/in.h
%% IPPROTO_TCP = 6
%%
%% include/netinet/tcp.h
%% #define TCP_INFO 11
%%
{raw, 6, 11, 1};
tcp_info_opt({unix, darwin}) ->
%% include/netinet/in.h
%% #define IPPROTO_TCP 6
%%
%% netinet/tcp.h
%% #define TCP_CONNECTION_INFO 0x106
%%
{raw, 6, 16#106, 1};
tcp_info_opt({unix, freebsd}) ->
%% sys/netinet/in.h
%% #define IPPROTO_TCP 6 /* tcp */
%%
%% sys/netinet/tcp.h
%% #define TCP_INFO 32 /* retrieve tcp_info structure */
%%
{raw, 6, 32, 1};
tcp_info_opt({_, _}) ->
undefined.
tcp_fsm_state(State, {unix, linux}) ->
%% netinet/tcp.h
%% enum
%% {
%% TCP_ESTABLISHED = 1,
%% TCP_SYN_SENT,
%% TCP_SYN_RECV,
%% TCP_FIN_WAIT1,
%% TCP_FIN_WAIT2,
%% TCP_TIME_WAIT,
%% TCP_CLOSE,
%% TCP_CLOSE_WAIT,
%% TCP_LAST_ACK,
%% TCP_LISTEN,
%% TCP_CLOSING
%% }
%%
lists:member(State, [4, 5, 6, 7, 8, 9, 10]);
tcp_fsm_state(State, {unix, darwin}) ->
%% netinet/tcp_fsm.h
%% #define TCPS_CLOSED 0 /* closed */
%% #define TCPS_LISTEN 1 /* listening for connection
*/
%% #define TCPS_SYN_SENT 2 /* active, have sent syn */
%% #define TCPS_SYN_RECEIVED 3 /* have send and received
syn */
%% #define TCPS_ESTABLISHED 4 /* established */
%% #define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for
close */
%% #define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */
%% #define TCPS_CLOSING 7 /* closed xchd FIN; await
FIN ACK */
%% #define TCPS_LAST_ACK 8 /* had fin and close; await
FIN ACK */
%% #define TCPS_FIN_WAIT_2 9 /* have closed, fin is
acked */
%% #define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait
after close */
%%
lists:member(State, [0, 5, 6, 7, 8, 9, 10]);
tcp_fsm_state(State, {unix, freebsd}) ->
%% netinet/tcp_fsm.h
%% #define TCPS_CLOSED 0 /* closed */
%% #define TCPS_LISTEN 1 /* listening for connection */
%% #define TCPS_SYN_SENT 2 /* active, have sent syn */
%% #define TCPS_SYN_RECEIVED 3 /* have sent and received syn */
%% #define TCPS_ESTABLISHED 4 /* established */
%% #define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */
%% #define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */
%% #define TCPS_CLOSING 7/* closed xchd FIN; await FIN ACK */
%% #define TCPS_LAST_ACK 8/* had fin and close; await FIN ACK */
%% #define TCPS_FIN_WAIT_2 9/* have closed, fin is acked */
%% #define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */
%%
lists:member(State, [0, 5, 6, 7, 8, 9, 10]).
monitor_loop(Sock) ->
timer:sleep(1000),
io:format("[mon] is_closed: ~p~n", [is_closed(Sock)]),
monitor_loop(Sock).
client(Port) ->
timer:sleep(1000),
io:format("[client] connecting on ~p~n", [Port]),
{ok, ClientSock} = gen_tcp:connect("127.0.0.1", Port, [{active, false},
binary]),
io:format("[client] connected ~p sleeping for 5 seconds and exiting~n",
[ClientSock]),
timer:sleep(5000),
io:format("[client] exiting ~n", []),
ok.
main(_) ->
{ok, ListenSocket} = gen_tcp:listen(0, [binary, {active, false}]),
{ok, Port} = inet:port(ListenSocket),
io:format("[srv] spawning client to connect to port ~p~n", [Port]),
spawn_link(fun() -> client(Port) end),
{ok, ClientSocket} = gen_tcp:accept(ListenSocket),
io:format("[srv] accepted a connection ~p, sleeping for 10 seconds then
exiting ~n", [ClientSocket]),
spawn_link(fun() -> monitor_loop(ClientSocket) end),
timer:sleep(10000).
```
```
./tcp_server_erlang.escript
[srv] spawning client to connect to port 59121
[client] connecting on 59121
[srv] accepted a connection #Port<0.8>, sleeping for 10 seconds then exiting
[client] connected #Port<0.7> sleeping for 5 seconds and exiting
[mon] is_closed: false
[mon] is_closed: false
[mon] is_closed: false
[mon] is_closed: false
[client] exiting
[mon] is_closed: true
[mon] is_closed: true
[mon] is_closed: true
[mon] is_closed: true
[mon] is_closed: true
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]