Packages
redix
0.2.1
1.6.0
1.5.3
1.5.2
1.5.1
1.5.0
1.4.2
1.4.1
1.4.0
1.3.0
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
retired
1.1.0
1.0.0
0.11.2
0.11.1
0.11.0
0.10.7
0.10.6
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.1
0.7.0
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.0
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.0
Fast, pipelined, resilient Redis driver for Elixir.
Current section
Files
Jump to
Current section
Files
lib/redix/connection/auth.ex
defmodule Redix.Connection.Auth do
@moduledoc false
alias Redix.Protocol
@doc """
Authenticates and selects the right database based on the state `s`.
This function checks the state `s` to see if in the options a password and/or
a database are specified. If a password is specified, then this function will
send the appropriate `AUTH` command to the Redis connection in `s.socket`. If
a database is specified, then the appropriate `SELECT` command will be issued.
"""
@spec auth_and_select_db(Redix.Connection.state) ::
{:ok, Redix.Connection.state} | {:stop, term, Redix.Connection.state}
def auth_and_select_db(s) do
case auth(s, s.opts[:password]) do
{:ok, s} ->
case select_db(s, s.opts[:database]) do
{:ok, s} ->
:ok = :inet.setopts(s.socket, active: :once)
{:ok, s}
o ->
o
end
o ->
o
end
end
defp auth(s, nil) do
{:ok, s}
end
defp auth(%{socket: socket} = s, password) when is_binary(password) do
case :gen_tcp.send(socket, Protocol.pack(["AUTH", password])) do
:ok ->
case wait_for_response(s) do
{:ok, "OK", s} ->
s = put_in(s.opts[:password], :redacted)
{:ok, s}
{:ok, error, s} ->
{:stop, error, s}
{:error, reason} ->
{:stop, reason, s}
end
{:error, reason} ->
{:stop, reason, s}
end
end
defp select_db(s, nil) do
{:ok, s}
end
defp select_db(%{socket: socket} = s, db) do
case :gen_tcp.send(socket, Protocol.pack(["SELECT", db])) do
:ok ->
case wait_for_response(s) do
{:ok, "OK", s} ->
{:ok, s}
{:ok, error, s} ->
{:stop, error, s}
{:error, reason} ->
{:stop, reason, s}
end
{:error, reason} ->
{:stop, reason, s}
end
end
defp wait_for_response(%{socket: socket} = s) do
case :gen_tcp.recv(socket, 0) do
{:ok, data} ->
data = s.tail <> data
case Protocol.parse(data) do
{:ok, value, rest} ->
{:ok, value, %{s | tail: rest}}
{:error, :incomplete} ->
wait_for_response(%{s | tail: data})
end
{:error, _} = err ->
err
end
end
end