Skip to content

Commit

Permalink
getsockname mirrors UNIX getsockname now. Added getpeername.
Browse files Browse the repository at this point in the history
  • Loading branch information
amitmurthy committed May 22, 2017
1 parent e5fb87d commit 35e3896
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 49 deletions.
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ Julia v0.7.0 Release Notes

New language features
---------------------
* `getpeername` on a `TCPSocket` returns the address and port of the remote
endpoint of the TCP connection ([#21825]).


Language changes
Expand All @@ -24,6 +26,9 @@ This section lists changes that do not have deprecation warnings.

* Passing the same keyword argument multiple times is now a syntax error ([#16937]).

* `getsockname` on a `TCPSocket` now returns the locally bound address and port
of the socket. Previously the address of the remote endpoint was being
returned ([#21825]).

Library improvements
--------------------
Expand Down
2 changes: 1 addition & 1 deletion base/distributed/managers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ function bind_client_port(s)
s.handle, hton(client_port[]), hton(UInt32(0)), 0)
Base.uv_error("bind() failed", err)

_addr, port = Base._sockname(s, true)
_addr, port = getsockname(s)
client_port[] = port
return s
end
Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,7 @@ export
getaddrinfo,
gethostname,
getipaddr,
getpeername,
getsockname,
htol,
hton,
Expand Down
21 changes: 15 additions & 6 deletions base/socket.jl
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,7 @@ function listenany(host::IPAddr, default_port)
sock = TCPServer()
if bind(sock, addr) && trylisten(sock) == 0
if default_port == 0
_addr, port = _sockname(sock, true)
_addr, port = getsockname(sock)
return (port, sock)
end
return (addr.port, sock)
Expand All @@ -845,15 +845,24 @@ listenany(default_port) = listenany(IPv4(UInt32(0)), default_port)
"""
getsockname(sock::Union{TCPServer, TCPSocket}) -> (IPAddr, UInt16)
Get the IP address and the port that the given `TCPSocket` is connected to
(or bound to, in the case of `TCPServer`).
Get the IP address and port that the given socket is bound to.
"""
getsockname(sock::Union{TCPServer, TCPSocket}) = _sockname(sock, isa(sock, TCPServer))
getsockname(sock::Union{TCPSocket, TCPServer}) = _sockname(sock, true)

function _sockname(sock, self)

"""
getpeername(sock::TCPSocket) -> (IPAddr, UInt16)
Get the IP address and port of the remote endpoint that the given
socket is connected to. Valid only for connected TCP sockets.
"""
getpeername(sock::TCPSocket) = _sockname(sock, false)

function _sockname(sock, self=true)
rport = Ref{Cushort}(0)
raddress = zeros(UInt8, 16)
rfamily = Ref{Cuint}(0)

if self
r = ccall(:jl_tcp_getsockname, Int32,
(Ptr{Void}, Ref{Cushort}, Ptr{Void}, Ref{Cuint}),
Expand Down Expand Up @@ -886,7 +895,7 @@ function _sockname(sock, self)
naddr = ntoh(unsafe_load(Ptr{UInt128}(pointer(raddress)), 1))
addr = IPv6(naddr)
else
error("unsupported address family: $(getindex(rfamily))")
error(string("unsupported address family: ", getindex(rfamily)))
end
else
error("cannot obtain socket name")
Expand Down
1 change: 1 addition & 0 deletions doc/src/stdlib/io-network.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ Base.listen(::Any)
Base.listen(::AbstractString)
Base.getaddrinfo
Base.getsockname
Base.getpeername
Base.IPv4
Base.IPv6
Base.nb_available
Expand Down
63 changes: 21 additions & 42 deletions test/socket.jl
Original file line number Diff line number Diff line change
Expand Up @@ -193,56 +193,35 @@ if !is_windows() || Sys.windows_version() >= Sys.WINDOWS_VISTA_VER
end

begin
default_port = UInt16(11011)
default_addr = IPv4("127.0.0.1")
for (addr, porthint) in [(IPv4("127.0.0.1"), UInt16(11011)),
(IPv6("::1"), UInt16(11012)), (getipaddr(), UInt16(11013))]
port, listen_sock = listenany(addr, porthint)
gsn_addr, gsn_port = getsockname(listen_sock)

sock = Base.TCPServer()
bind(sock,Base.InetAddr(default_addr,default_port))
listen(sock)
@test addr == gsn_addr
@test port == gsn_port

new_addr, new_port = getsockname(sock)
@test_throws MethodError getpeername(listen_sock)

@test default_addr == new_addr
@test default_port == new_port
close(sock)
end
# connect to it
client_sock = connect(addr, port)
server_sock = accept(listen_sock)

begin
default_port = UInt16(21011)
default_addr = IPv6("::1")
self_client_addr, self_client_port = getsockname(client_sock)
peer_client_addr, peer_client_port = getpeername(client_sock)
self_srvr_addr, self_srvr_port = getsockname(server_sock)
peer_srvr_addr, peer_srvr_port = getpeername(server_sock)

sock = Base.TCPServer()
addr = Base.InetAddr(default_addr,default_port)
bind(sock,addr)
listen(sock)
@test self_client_addr == peer_client_addr == self_srvr_addr == peer_srvr_addr

new_addr, new_port = getsockname(sock)
@test peer_client_port == self_srvr_port
@test peer_srvr_port == self_client_port
@test self_srvr_port != self_client_port

@test default_addr == new_addr
@test default_port == new_port
close(sock)
end

begin
default_port = UInt16(11011)
default_addr = getipaddr()

sock = Base.TCPServer()
bind(sock,Base.InetAddr(default_addr,default_port))
listen(sock)

@async begin
sleep(1)
ssock = connect(default_addr, default_port)
close(listen_sock)
close(client_sock)
close(server_sock)
end

csock = accept(sock)
new_addr, new_port = getsockname(csock)

@test default_addr == new_addr
@test new_port > 0
close(csock)
close(sock)
end

# Local-machine broadcast
Expand Down

0 comments on commit 35e3896

Please sign in to comment.