Current section

Files

Jump to
net_address lib ip sock_addr.ex
Raw

lib/ip/sock_addr.ex

defmodule IP.SockAddr do
@moduledoc """
Tools for handling the `t::socket.sockaddr_in4/0` type.
Unless you're using the `:socket` library, for low level socket
access you probably won't need this module!
Support for inet6 forthcoming.
"""
@enforce_keys [:family, :addr, :port]
defstruct @enforce_keys ++ [:flowinfo, :scope_id]
@type t :: :socket.sockaddr_in4 |
:socket.sockaddr_in6
@spec from_string!(String.t) :: t
@doc """
Creates an elixir struct, which is compatible with `:socket` module's
sockaddr_in4 type.
You may pass this, for example to `:socket.bind/2`
"""
def from_string!(sockaddr_str) do
case from_string(sockaddr_str) do
{:ok, sockaddr} -> sockaddr
_ ->
raise ArgumentError, "invalid sockaddr string: \"#{sockaddr_str}\""
end
end
@spec from_string(String.t) :: {:ok, t} | {:error, term}
@doc """
Like `from_string/1`, but returns an ok or error tuple on failure.
"""
def from_string(sockaddr_str) do
with [addr_str, port_str] <- String.split(sockaddr_str, ":"),
{:ok, addr} <- IP.from_string(addr_str),
{port, ""} when 0 <= port and port <= 65535 <- Integer.parse(port_str) do
{:ok, %__MODULE__{family: :inet, addr: addr, port: port}}
else
list when is_list(list) -> {:error, :einval}
:error -> {:error, :einval}
{port, ""} -> {:error, "port #{port} not in range"}
error -> error
end
end
@spec to_string(t) :: String.t
@doc """
converts a `t::socket.sockaddr_in4` value to
Compatible with sockaddr maps returned by the socket library, not
selective on the `IP.SockAddr` struct.
"""
def to_string(sockaddr = %{family: :inet}) do
"#{IP.to_string sockaddr.addr}:#{sockaddr.port}"
end
end
defimpl Inspect, for: IP.SockAddr do
import Inspect.Algebra
def inspect(subnet, _opts) do
concat(["~i\"", IP.SockAddr.to_string(subnet) , "\""])
end
end