Packages
redix
0.4.0
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/auth.ex
defmodule Redix.Auth do
@moduledoc false
alias Redix.Protocol
@doc """
Authenticates and selects the right database based on the state `state`.
This function checks the given options to see if 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 `state.socket`. If a
database is specified, then the appropriate `SELECT` command will be issued.
The socket is expected to be in passive mode, and will be returned in passive
mode to the caller.
"""
@spec auth_and_select_db(:gen_tcp.socket, Keyword.t) :: {:ok, binary} | {:error, term}
def auth_and_select_db(socket, opts) do
# TODO: this *begs* for `with` once we depend on ~> 1.2.
case auth(socket, opts[:password]) do
{:ok, tail} ->
select_db(socket, opts[:database], tail)
{:error, _reason} = error ->
error
end
end
@spec auth(:gen_tcp.socket, nil | binary) :: {:ok | binary} | {:error, term}
defp auth(socket, password)
defp auth(_socket, nil) do
{:ok, ""}
end
defp auth(socket, password) when is_binary(password) do
case :gen_tcp.send(socket, Protocol.pack(["AUTH", password])) do
:ok ->
case blocking_recv(socket, "") do
{:ok, "OK", tail} ->
{:ok, tail}
{:ok, error, _tail} ->
{:error, error}
{:error, _reason} = error ->
error
end
{:error, _reason} = error ->
error
end
end
@spec select_db(:gen_tcp.socket, nil | non_neg_integer | binary, binary) :: {:ok, binary} | {:error, term}
defp select_db(socket, db, tail)
defp select_db(_socket, nil, tail) do
{:ok, tail}
end
defp select_db(socket, db, tail) do
case :gen_tcp.send(socket, Protocol.pack(["SELECT", db])) do
:ok ->
case blocking_recv(socket, tail) do
{:ok, "OK", tail} ->
{:ok, tail}
{:ok, error, _state} ->
{:error, error}
{:error, _reason} = error ->
error
end
{:error, _reason} = error ->
error
end
end
@spec blocking_recv(:gen_tcp.socket, binary, nil | (binary -> term)) :: {:ok, term, binary} | {:error, term}
defp blocking_recv(socket, tail, continuation \\ nil) do
case :gen_tcp.recv(socket, 0) do
{:ok, data} ->
parser = continuation || &Protocol.parse/1
case parser.(tail <> data) do
{:ok, _resp, _rest} = result ->
result
{:continuation, continuation} ->
blocking_recv(socket, "", continuation)
end
{:error, _reason} = error ->
error
end
end
end